├── .gitattributes
├── .github
└── workflows
│ ├── ci.yml
│ ├── github-release.yml
│ └── publish.yml
├── .gitignore
├── .husky
├── .gitignore
└── pre-commit
├── .prettierignore
├── CHANGELOG.md
├── LICENSE
├── MIGRATION.md
├── README.md
├── client.d.ts
├── client.mjs
├── package.json
├── pnpm-lock.yaml
├── src
├── devBuilder
│ ├── devBuilder.ts
│ ├── devBuilderManifestV2.ts
│ └── devBuilderManifestV3.ts
├── index.ts
├── manifestParser
│ ├── manifestParser.ts
│ ├── manifestParserFactory.ts
│ ├── manifestV2.ts
│ └── manifestV3.ts
├── middleware
│ └── viteClientModifier.ts
└── utils
│ ├── addHmrSupportToCsp.ts
│ ├── file.ts
│ ├── getAdditionalInputAsWebAccessibleResource.ts
│ ├── getNormalizedAdditionalInput.ts
│ ├── loader.ts
│ ├── rollup.ts
│ ├── virtualModule.ts
│ └── vite.ts
├── test
├── manifest
│ ├── __snapshots__
│ │ ├── additionalInputsHtml.v2.test.ts.snap
│ │ ├── additionalInputsHtml.v3.test.ts.snap
│ │ ├── additionalInputsScriptsChunkedImport.v2.test.ts.snap
│ │ ├── additionalInputsScriptsChunkedImport.v3.test.ts.snap
│ │ ├── additionalInputsScriptsNoImport.v2.test.ts.snap
│ │ ├── additionalInputsScriptsNoImport.v3.test.ts.snap
│ │ ├── additionalInputsScriptsTypes.v2.test.ts.snap
│ │ ├── additionalInputsScriptsTypes.v3.test.ts.snap
│ │ ├── additionalInputsScriptsUnchunkedImport.v2.test.ts.snap
│ │ ├── additionalInputsScriptsUnchunkedImport.v3.test.ts.snap
│ │ ├── additionalInputsStylesTypes.v2.test.ts.snap
│ │ ├── additionalInputsStylesTypes.v3.test.ts.snap
│ │ ├── additionalInputsWebAccessible.v2.test.ts.snap
│ │ ├── additionalInputsWebAccessible.v3.test.ts.snap
│ │ ├── additionalInputsWebAccessibleExcludeEntryFile.v2.test.ts.snap
│ │ ├── additionalInputsWebAccessibleExcludeEntryFile.v3.test.ts.snap
│ │ ├── backgroundHtml.v2.test.ts.snap
│ │ ├── backgroundScript.v2.test.ts.snap
│ │ ├── backgroundServiceWorker.v3.test.ts.snap
│ │ ├── backgroundServiceWorkerRelative.v3.test.ts.snap
│ │ ├── backgroundServiceWorkerRoot.v3.test.ts.snap
│ │ ├── chromeUrlOverridesHtmlBookmarks.v2.test.ts.snap
│ │ ├── chromeUrlOverridesHtmlBookmarks.v3.test.ts.snap
│ │ ├── chromeUrlOverridesHtmlHistory.v2.test.ts.snap
│ │ ├── chromeUrlOverridesHtmlHistory.v3.test.ts.snap
│ │ ├── chromeUrlOverridesHtmlNewTab.v2.test.ts.snap
│ │ ├── chromeUrlOverridesHtmlNewTab.v3.test.ts.snap
│ │ ├── chunkCssRewrite.v2.test.ts.snap
│ │ ├── chunkCssRewrite.v3.test.ts.snap
│ │ ├── contentCss.v2.test.ts.snap
│ │ ├── contentCss.v3.test.ts.snap
│ │ ├── contentScriptPaths.v2.test.ts.snap
│ │ ├── contentScriptPaths.v3.test.ts.snap
│ │ ├── contentScriptTypes.v2.test.ts.snap
│ │ ├── contentScriptTypes.v3.test.ts.snap
│ │ ├── contentWithChunkedImport.v2.test.ts.snap
│ │ ├── contentWithChunkedImport.v3.test.ts.snap
│ │ ├── contentWithDynamicImport.v2.test.ts.snap
│ │ ├── contentWithDynamicImport.v3.test.ts.snap
│ │ ├── contentWithNoImports.v2.test.ts.snap
│ │ ├── contentWithNoImports.v3.test.ts.snap
│ │ ├── contentWithSameScriptName.v2.test.ts.snap
│ │ ├── contentWithSameScriptName.v3.test.ts.snap
│ │ ├── contentWithUnchunkedImport.v2.test.ts.snap
│ │ ├── contentWithUnchunkedImport.v3.test.ts.snap
│ │ ├── devtoolsHtml.v2.test.ts.snap
│ │ ├── devtoolsHtml.v3.test.ts.snap
│ │ ├── fullExtension.v2.test.ts.snap
│ │ ├── fullExtension.v3.test.ts.snap
│ │ ├── htmlUrlProperties.v2.test.ts.snap
│ │ ├── htmlUrlProperties.v3.test.ts.snap
│ │ ├── optimizeWebAccessibleResourcesDisabled.v2.test.ts.snap
│ │ ├── optimizeWebAccessibleResourcesDisabled.v3.test.ts.snap
│ │ ├── optimizeWebAccessibleResourcesEnabled.v2.test.ts.snap
│ │ ├── optimizeWebAccessibleResourcesEnabled.v3.test.ts.snap
│ │ ├── optionsHtml.v2.test.ts.snap
│ │ ├── optionsHtml.v3.test.ts.snap
│ │ ├── popupHtml.v2.test.ts.snap
│ │ ├── popupHtml.v3.test.ts.snap
│ │ ├── sidePanelHtml.v3.test.ts.snap
│ │ ├── useDynamicUrlWebAccessibleResourcesDisabled.v3.test.ts.snap
│ │ ├── useDynamicUrlWebAccessibleResourcesEnabled.v3.test.ts.snap
│ │ └── useDynamicUrlWebAccessibleResourcesUndefined.v3.test.ts.snap
│ ├── additionalInputsHtml.v2.test.ts
│ ├── additionalInputsHtml.v3.test.ts
│ ├── additionalInputsScriptsChunkedImport.v2.test.ts
│ ├── additionalInputsScriptsChunkedImport.v3.test.ts
│ ├── additionalInputsScriptsNoImport.v2.test.ts
│ ├── additionalInputsScriptsNoImport.v3.test.ts
│ ├── additionalInputsScriptsTypes.v2.test.ts
│ ├── additionalInputsScriptsTypes.v3.test.ts
│ ├── additionalInputsScriptsUnchunkedImport.v2.test.ts
│ ├── additionalInputsScriptsUnchunkedImport.v3.test.ts
│ ├── additionalInputsStylesTypes.v2.test.ts
│ ├── additionalInputsStylesTypes.v3.test.ts
│ ├── additionalInputsWebAccessible.v2.test.ts
│ ├── additionalInputsWebAccessible.v3.test.ts
│ ├── additionalInputsWebAccessibleExcludeEntryFile.v2.test.ts
│ ├── additionalInputsWebAccessibleExcludeEntryFile.v3.test.ts
│ ├── backgroundHtml.v2.test.ts
│ ├── backgroundScript.v2.test.ts
│ ├── backgroundServiceWorker.v3.test.ts
│ ├── backgroundServiceWorkerRelative.v3.test.ts
│ ├── backgroundServiceWorkerRoot.v3.test.ts
│ ├── chromeUrlOverridesHtmlBookmarks.v2.test.ts
│ ├── chromeUrlOverridesHtmlBookmarks.v3.test.ts
│ ├── chromeUrlOverridesHtmlHistory.v2.test.ts
│ ├── chromeUrlOverridesHtmlHistory.v3.test.ts
│ ├── chromeUrlOverridesHtmlNewTab.v2.test.ts
│ ├── chromeUrlOverridesHtmlNewTab.v3.test.ts
│ ├── chunkCssRewrite.v2.test.ts
│ ├── chunkCssRewrite.v3.test.ts
│ ├── contentCss.v2.test.ts
│ ├── contentCss.v3.test.ts
│ ├── contentScriptPaths.v2.test.ts
│ ├── contentScriptPaths.v3.test.ts
│ ├── contentScriptTypes.v2.test.ts
│ ├── contentScriptTypes.v3.test.ts
│ ├── contentWithChunkedImport.v2.test.ts
│ ├── contentWithChunkedImport.v3.test.ts
│ ├── contentWithDynamicImport.v2.test.ts
│ ├── contentWithDynamicImport.v3.test.ts
│ ├── contentWithNoImports.v2.test.ts
│ ├── contentWithNoImports.v3.test.ts
│ ├── contentWithSameScriptName.v2.test.ts
│ ├── contentWithSameScriptName.v3.test.ts
│ ├── contentWithUnchunkedImport.v2.test.ts
│ ├── contentWithUnchunkedImport.v3.test.ts
│ ├── devtoolsHtml.v2.test.ts
│ ├── devtoolsHtml.v3.test.ts
│ ├── fullExtension.v2.test.ts
│ ├── fullExtension.v3.test.ts
│ ├── htmlUrlProperties.v2.test.ts
│ ├── htmlUrlProperties.v3.test.ts
│ ├── manifestTestUtils.ts
│ ├── optimizeWebAccessibleResourcesDisabled.v2.test.ts
│ ├── optimizeWebAccessibleResourcesDisabled.v3.test.ts
│ ├── optimizeWebAccessibleResourcesEnabled.v2.test.ts
│ ├── optimizeWebAccessibleResourcesEnabled.v3.test.ts
│ ├── optionsHtml.v2.test.ts
│ ├── optionsHtml.v3.test.ts
│ ├── popupHtml.v2.test.ts
│ ├── popupHtml.v3.test.ts
│ ├── resources
│ │ ├── additionalInputsHtml
│ │ │ ├── html.html
│ │ │ ├── script.js
│ │ │ └── style.css
│ │ ├── additionalInputsScriptsChunkedImport
│ │ │ ├── script1.js
│ │ │ └── script2.js
│ │ ├── additionalInputsScriptsNoImport
│ │ │ ├── script1.js
│ │ │ └── script2.js
│ │ ├── additionalInputsScriptsTypes
│ │ │ ├── script1.js
│ │ │ └── script2.ts
│ │ ├── additionalInputsScriptsUnchunkedImport
│ │ │ ├── script1.js
│ │ │ └── script2.js
│ │ ├── additionalInputsStylesTypes
│ │ │ ├── style1.css
│ │ │ └── style2.scss
│ │ ├── additionalInputsWebAccessible
│ │ │ ├── chunkedScript1.js
│ │ │ ├── chunkedScript2.js
│ │ │ ├── chunkedScript3.js
│ │ │ ├── script1.js
│ │ │ ├── script2.js
│ │ │ ├── script3.js
│ │ │ ├── script4.js
│ │ │ ├── script5.ts
│ │ │ ├── script6.js
│ │ │ └── script7.js
│ │ ├── backgroundHtml
│ │ │ ├── background.html
│ │ │ └── background.js
│ │ ├── backgroundScript
│ │ │ ├── background.html
│ │ │ └── background.js
│ │ ├── backgroundServiceWorker
│ │ │ └── serviceWorker.js
│ │ ├── chromeUrlOverridesHtml
│ │ │ ├── bookmarks.html
│ │ │ ├── chromeUrlOverridesHtml.js
│ │ │ ├── devtools.html
│ │ │ ├── history.html
│ │ │ └── newtab.html
│ │ ├── chunkCssRewrite
│ │ │ ├── content1.css
│ │ │ ├── content1.js
│ │ │ ├── content2.css
│ │ │ ├── content2.js
│ │ │ ├── contentNoCss.js
│ │ │ └── contentShared.css
│ │ ├── contentCss
│ │ │ ├── content.js
│ │ │ ├── content1.css
│ │ │ └── content2.scss
│ │ ├── contentScriptTypes
│ │ │ ├── content1.js
│ │ │ └── content2.ts
│ │ ├── contentWithChunkedImport
│ │ │ ├── content1.js
│ │ │ └── content2.js
│ │ ├── contentWithDynamicImport
│ │ │ ├── content1.js
│ │ │ └── content2.js
│ │ ├── contentWithNoImports
│ │ │ └── content.js
│ │ ├── contentWithSameScriptName
│ │ │ ├── content1
│ │ │ │ └── content.js
│ │ │ └── content2
│ │ │ │ └── content.js
│ │ ├── contentWithUnchunkedImport
│ │ │ └── content.js
│ │ ├── devtoolsHtml
│ │ │ ├── devtools.html
│ │ │ └── devtools.js
│ │ ├── fullExtension
│ │ │ └── src
│ │ │ │ ├── assets
│ │ │ │ └── logo.svg
│ │ │ │ ├── entries
│ │ │ │ ├── background
│ │ │ │ │ └── main.js
│ │ │ │ ├── contentScript
│ │ │ │ │ ├── primary
│ │ │ │ │ │ ├── main.js
│ │ │ │ │ │ └── style.css
│ │ │ │ │ └── renderContent.js
│ │ │ │ ├── options
│ │ │ │ │ ├── index.html
│ │ │ │ │ ├── main.js
│ │ │ │ │ └── style.css
│ │ │ │ └── popup
│ │ │ │ │ ├── index.html
│ │ │ │ │ ├── main.js
│ │ │ │ │ └── style.css
│ │ │ │ └── lib.js
│ │ ├── htmlUrlProperties
│ │ │ ├── devtools.html
│ │ │ ├── devtools.js
│ │ │ ├── options.html
│ │ │ ├── options.js
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── optimizeWebAccessibleResources
│ │ │ ├── content1.js
│ │ │ ├── content2.js
│ │ │ ├── script1.js
│ │ │ └── script2.js
│ │ ├── optionsHtml
│ │ │ ├── options.html
│ │ │ └── options.js
│ │ ├── popupHtml
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── shared
│ │ │ └── log.js
│ │ ├── sidePanelHtml
│ │ │ ├── sidepanel.html
│ │ │ └── sidepanel.js
│ │ └── useDynamicUrlWebAccessibleResources
│ │ │ ├── content1.js
│ │ │ ├── content2.js
│ │ │ ├── script1.js
│ │ │ └── script2.js
│ ├── sidePanelHtml.v3.test.ts
│ ├── useDynamicUrlWebAccessibleResourcesDisabled.v3.test.ts
│ ├── useDynamicUrlWebAccessibleResourcesEnabled.v3.test.ts
│ └── useDynamicUrlWebAccessibleResourcesUndefined.v3.test.ts
└── utils
│ ├── addHmrSupportToCsp.test.ts
│ └── rollup.test.ts
├── tsconfig.json
└── types
└── index.d.ts
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
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: ${{ matrix.os }}
12 |
13 | strategy:
14 | matrix:
15 | os: [ubuntu-latest, windows-latest]
16 |
17 | steps:
18 | - name: Checkout
19 | uses: actions/checkout@v3
20 |
21 | - name: Install pnpm
22 | uses: pnpm/action-setup@v4.0.0
23 |
24 | - name: Setup node
25 | uses: actions/setup-node@v4.0.4
26 | with:
27 | node-version: 18.x
28 | registry-url: https://registry.npmjs.org/
29 | cache: "pnpm"
30 |
31 | - name: Install dependencies
32 | run: pnpm install
33 |
34 | - name: Check formatting
35 | run: pnpm lint:check
36 |
37 | - name: Test
38 | run: pnpm test
39 |
40 | - name: Build
41 | run: pnpm build
42 |
--------------------------------------------------------------------------------
/.github/workflows/github-release.yml:
--------------------------------------------------------------------------------
1 | name: Create Github Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - "v*"
7 |
8 | jobs:
9 | release:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v3
15 |
16 | - name: Extract release notes
17 | id: extract-release-notes
18 | uses: ffurrer2/extract-release-notes@v1
19 |
20 | - name: Create release
21 | run: |
22 | gh release create "${GITHUB_REF#refs/tags/}" -n "$RELEASE_NOTES"
23 | env:
24 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
25 | RELEASE_NOTES: ${{ steps.extract-release-notes.outputs.release_notes }}
26 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish Package
2 |
3 | on:
4 | push:
5 | tags:
6 | - "v*"
7 |
8 | jobs:
9 | publish:
10 | runs-on: ubuntu-latest
11 | permissions:
12 | id-token: write
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v3
16 |
17 | - name: Install pnpm
18 | uses: pnpm/action-setup@v4.0.0
19 |
20 | - name: Setup node
21 | uses: actions/setup-node@v4.0.4
22 | with:
23 | node-version: 18.x
24 | registry-url: https://registry.npmjs.org/
25 | cache: "pnpm"
26 |
27 | - name: Install dependencies
28 | run: pnpm install
29 |
30 | - name: Publish package
31 | run: pnpm publish --access public --no-git-checks
32 | env:
33 | NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
34 | NPM_CONFIG_PROVENANCE: true
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/node_modules/
2 | **/dist/
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | pnpm exec lint-staged
5 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | **/node_modules/
2 | pnpm-lock.yaml
3 | dist/
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022-present Ruben Medina
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MIGRATION.md:
--------------------------------------------------------------------------------
1 | # Migration
2 |
3 | - [Version 4.x.x to 5.0.0](#version-4xx-to-500)
4 | - [Version 3.x.x to 4.0.0](#version-3xx-to-400)
5 | - [Version 2.x.x to 3.0.0](#version-2xx-to-300)
6 | - [Version 0.x.x to 1.0.0](#version-0xx-to-100)
7 |
8 | ## Version 4.x.x to 5.0.0
9 |
10 | - The `devHtmlTransform` plugin option has been removed. Vite's dev HTML transform functionality is now required to support HTML files in dev (HMR) mode. In dev mode, a element with the dev server url for the HTML file is injected into the page. This replaces incomplete custom logic for handling resources in HTML files.
11 |
12 | ## Version 3.x.x to 4.0.0
13 |
14 | - Dev mode HTML transforms are no longer applied by default. Enable via the new devHtmlTransform option if still needed.
15 | - The useDynamicUrlContentScripts option has been renamed to useDynamicUrlWebAccessibleResources
16 | - The webAccessibleScripts option has been removed and replaced by the additionalInputs option. For similar functionality, move scripts to additionalInputs.scripts and html files to additionalInputs.html. Check the README for detailed usage instructions.
17 |
18 | ## Version 2.x.x to 3.0.0
19 |
20 | - Upgrade Vite to 4.0.3
21 |
22 | - Upgrade any Vite framework plugins
23 |
24 | - The build.modulePreload Vite config option is now defaulted to false by the plugin. Prevent using this default by defining the option in your project's Vite config.
25 |
26 | ## Version 0.x.x to 1.0.0
27 |
28 | - Upgrade Vite to 2.9.x
29 |
30 | - Upgrade any Vite framework plugins
31 |
32 | - Replace usages of `import.meta.CURRENT_CONTENT_SCRIPT_CSS_URL` with `import.meta.PLUGIN_WEB_EXT_CHUNK_CSS_PATHS`
33 |
34 | - `import.meta.PLUGIN_WEB_EXT_CHUNK_CSS_PATHS` is replaced with an array of css paths at build time, so update existing code that expects a single string to properly handle an array of strings.
35 |
36 | - Replace usages of `addStyleTarget` from `/@vite/client` with `addViteStyleTarget` from `@samrum/vite-plugin-web-extension/client`:
37 |
38 | ```js
39 | const { addStyleTarget } = await import("/@vite/client");
40 |
41 | addStyleTarget(shadowRoot);
42 | ```
43 |
44 | to
45 |
46 | ```js
47 | const { addViteStyleTarget } = await import(
48 | "@samrum/vite-plugin-web-extension/client"
49 | );
50 |
51 | await addViteStyleTarget(shadowRoot);
52 | ```
53 |
54 | - If using TypeScript, add plugin client types to your `env.d.ts` file:
55 | ```ts
56 | ///
57 | ```
58 |
--------------------------------------------------------------------------------
/client.d.ts:
--------------------------------------------------------------------------------
1 | interface ImportMeta {
2 | PLUGIN_WEB_EXT_CHUNK_CSS_PATHS: string[];
3 | }
4 |
5 | declare module "@samrum/vite-plugin-web-extension/client" {
6 | export function addViteStyleTarget(element: Node): Promise;
7 | }
8 |
--------------------------------------------------------------------------------
/client.mjs:
--------------------------------------------------------------------------------
1 | export async function addViteStyleTarget(element) {
2 | const { addStyleTarget } = await import("/@vite/client");
3 |
4 | addStyleTarget(element);
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@samrum/vite-plugin-web-extension",
3 | "version": "5.1.1",
4 | "description": "A vite plugin for generating cross browser platform, ES module based web extensions",
5 | "main": "./dist/index.cjs",
6 | "module": "./dist/index.mjs",
7 | "types": "./types/index.d.ts",
8 | "type": "module",
9 | "exports": {
10 | ".": {
11 | "types": "./types/index.d.ts",
12 | "import": "./dist/index.mjs",
13 | "require": "./dist/index.cjs"
14 | },
15 | "./client": {
16 | "types": "./client.d.ts",
17 | "import": "./client.mjs",
18 | "require": "./client.mjs"
19 | }
20 | },
21 | "engines": {
22 | "node": ">=16.0.0"
23 | },
24 | "packageManager": "pnpm@8.3.1",
25 | "files": [
26 | "client.mjs",
27 | "client.d.ts",
28 | "dist",
29 | "README.md",
30 | "types"
31 | ],
32 | "scripts": {
33 | "build": "unbuild",
34 | "dev": "unbuild --stub",
35 | "lint": "prettier --write --loglevel warn .",
36 | "lint:check": "prettier --check .",
37 | "test": "vitest",
38 | "test:run": "vitest run",
39 | "prepare": "husky install",
40 | "prepublishOnly": "pnpm run build",
41 | "release": "standard-version --sign"
42 | },
43 | "standard-version": {
44 | "scripts": {
45 | "prerelease": "pnpm test:run && pnpm build"
46 | }
47 | },
48 | "repository": {
49 | "type": "git",
50 | "url": "git+https://github.com/samrum/vite-plugin-web-extension.git"
51 | },
52 | "keywords": [
53 | "vite",
54 | "vite-plugin",
55 | "web",
56 | "extension",
57 | "browser",
58 | "chrome",
59 | "firefox",
60 | "edge",
61 | "manifest",
62 | "manifest V2",
63 | "manifest V3"
64 | ],
65 | "author": "Ruben Medina",
66 | "license": "MIT",
67 | "bugs": {
68 | "url": "https://github.com/samrum/vite-plugin-web-extension/issues"
69 | },
70 | "homepage": "https://github.com/samrum/vite-plugin-web-extension#readme",
71 | "devDependencies": {
72 | "@types/fs-extra": "^11.0.4",
73 | "@types/node": "^20.10.4",
74 | "husky": "^8.0.3",
75 | "lint-staged": "^15.2.0",
76 | "prettier": "2.8.8",
77 | "rollup": "^4.8.0",
78 | "sass": "^1.69.5",
79 | "standard-version": "^9.5.0",
80 | "typescript": "^5.3.3",
81 | "unbuild": "^2.0.0",
82 | "vitest": "^2.1.1"
83 | },
84 | "peerDependencies": {
85 | "vite": "^4.0.3 || ^5.0.0"
86 | },
87 | "lint-staged": {
88 | "*": [
89 | "prettier --write --cache --ignore-unknown"
90 | ]
91 | },
92 | "dependencies": {
93 | "@types/chrome": "^0.0.233",
94 | "@types/etag": "^1.8.3",
95 | "content-security-policy-parser": "^0.4.1",
96 | "etag": "^1.8.1",
97 | "fs-extra": "^11.2.0",
98 | "magic-string": "^0.30.5",
99 | "vite": "^5.0.7"
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/devBuilder/devBuilderManifestV2.ts:
--------------------------------------------------------------------------------
1 | import { createHash } from "node:crypto";
2 | import { ViteWebExtensionOptions } from "../../types";
3 | import DevBuilder from "./devBuilder";
4 |
5 | export default class DevBuilderManifestV2 extends DevBuilder {
6 | protected updateContentSecurityPolicyForHmr(): void {
7 | this.manifest.content_security_policy =
8 | this.getContentSecurityPolicyWithHmrSupport(
9 | this.manifest.content_security_policy
10 | );
11 | }
12 |
13 | protected parseInlineScriptHashes(content: string) {
14 | const matches = content.matchAll(/([^<]+)<\/script>/gs);
15 | for (const match of matches) {
16 | const shasum = createHash("sha256");
17 | shasum.update(match[1]);
18 |
19 | this.inlineScriptHashes.add(`'sha256-${shasum.digest("base64")}'`);
20 | }
21 | }
22 |
23 | protected async writeManifestAdditionalInputFiles(): Promise {
24 | if (!this.pluginOptions.additionalInputs) {
25 | return;
26 | }
27 |
28 | for (const [type, inputs] of Object.entries(
29 | this.pluginOptions.additionalInputs
30 | )) {
31 | if (!inputs) {
32 | return;
33 | }
34 |
35 | for (const input of inputs) {
36 | if (!input) {
37 | continue;
38 | }
39 |
40 | await this.writeManifestAdditionalInputFile(
41 | type as keyof NonNullable<
42 | ViteWebExtensionOptions["additionalInputs"]
43 | >,
44 | input
45 | );
46 | }
47 | }
48 | }
49 |
50 | protected addWebAccessibleResource({
51 | fileName,
52 | }: {
53 | fileName: string;
54 | webAccessibleResource: {
55 | matches: string[] | undefined;
56 | extension_ids: string[] | undefined;
57 | use_dynamic_url?: boolean;
58 | };
59 | }): void {
60 | this.manifest.web_accessible_resources ??= [];
61 | this.manifest.web_accessible_resources.push(fileName);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/devBuilder/devBuilderManifestV3.ts:
--------------------------------------------------------------------------------
1 | import { ensureDir } from "fs-extra";
2 | import { writeFile } from "node:fs/promises";
3 | import path from "node:path";
4 | import { ViteWebExtensionOptions } from "../../types";
5 | import { getServiceWorkerLoaderFile } from "../utils/loader";
6 | import DevBuilder from "./devBuilder";
7 |
8 | export default class DevBuilderManifestV3 extends DevBuilder {
9 | async writeBuildFiles(): Promise {
10 | await this.writeManifestServiceWorkerFiles(this.manifest);
11 | }
12 |
13 | updateContentSecurityPolicyForHmr(): void {
14 | this.manifest.content_security_policy ??= {};
15 |
16 | this.manifest.content_security_policy.extension_pages =
17 | this.getContentSecurityPolicyWithHmrSupport(
18 | this.manifest.content_security_policy.extension_pages
19 | );
20 | }
21 |
22 | private async writeManifestServiceWorkerFiles(
23 | manifest: chrome.runtime.ManifestV3
24 | ) {
25 | if (!manifest.background?.service_worker) {
26 | return;
27 | }
28 |
29 | const fileName = manifest.background?.service_worker;
30 |
31 | const serviceWorkerLoader = getServiceWorkerLoaderFile([
32 | this.hmrViteClientUrl,
33 | `${this.hmrServerOrigin}/${fileName}`,
34 | ]);
35 |
36 | manifest.background.service_worker = serviceWorkerLoader.fileName;
37 |
38 | const outFile = `${this.outDir}/${serviceWorkerLoader.fileName}`;
39 |
40 | const outFileDir = path.dirname(outFile);
41 |
42 | await ensureDir(outFileDir);
43 |
44 | await writeFile(outFile, serviceWorkerLoader.source);
45 | }
46 |
47 | protected async writeManifestAdditionalInputFiles(): Promise {
48 | if (!this.pluginOptions.additionalInputs) {
49 | return;
50 | }
51 |
52 | for (const [type, inputs] of Object.entries(
53 | this.pluginOptions.additionalInputs
54 | )) {
55 | if (!inputs) {
56 | return;
57 | }
58 |
59 | for (const input of inputs) {
60 | if (!input) {
61 | continue;
62 | }
63 |
64 | await this.writeManifestAdditionalInputFile(
65 | type as keyof NonNullable<
66 | ViteWebExtensionOptions["additionalInputs"]
67 | >,
68 | input
69 | );
70 | }
71 | }
72 | }
73 |
74 | protected addWebAccessibleResource({
75 | fileName,
76 | webAccessibleResource,
77 | }: {
78 | fileName: string;
79 | webAccessibleResource: {
80 | matches: string[] | undefined;
81 | extension_ids: string[] | undefined;
82 | use_dynamic_url?: boolean;
83 | };
84 | }): void {
85 | this.manifest.web_accessible_resources ??= [];
86 |
87 | if (this.pluginOptions.useDynamicUrlWebAccessibleResources !== true) {
88 | delete webAccessibleResource["use_dynamic_url"];
89 | }
90 |
91 | // @ts-expect-error - allow additional web_accessible_resources properties
92 | this.manifest.web_accessible_resources.push({
93 | resources: [fileName],
94 | ...webAccessibleResource,
95 | });
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import type { EmittedFile, OutputBundle } from "rollup";
2 | import type { Plugin, ResolvedConfig } from "vite";
3 | import type { ViteWebExtensionOptions } from "../types";
4 | import ManifestParser from "./manifestParser/manifestParser";
5 | import ManifestParserFactory from "./manifestParser/manifestParserFactory";
6 | import viteClientModifier from "./middleware/viteClientModifier";
7 | import { addInputScriptsToOptionsInput } from "./utils/rollup";
8 | import { getVirtualModule } from "./utils/virtualModule";
9 | import {
10 | transformSelfLocationAssets,
11 | updateConfigForExtensionSupport,
12 | } from "./utils/vite";
13 |
14 | export default function webExtension(
15 | pluginOptions: ViteWebExtensionOptions
16 | ): Plugin {
17 | if (!pluginOptions.manifest) {
18 | throw new Error("Missing manifest definition");
19 | }
20 |
21 | let viteConfig: ResolvedConfig;
22 | let emitQueue: EmittedFile[] = [];
23 | let manifestParser:
24 | | ManifestParser
25 | | ManifestParser;
26 |
27 | return {
28 | name: "webExtension",
29 | enforce: "post", // required to revert vite asset self.location transform to import.meta.url
30 |
31 | config(config) {
32 | return updateConfigForExtensionSupport(config, pluginOptions.manifest);
33 | },
34 |
35 | configResolved(resolvedConfig) {
36 | viteConfig = resolvedConfig;
37 | },
38 |
39 | configureServer(server) {
40 | server.middlewares.use(viteClientModifier);
41 |
42 | server.httpServer?.once("listening", () => {
43 | manifestParser.setDevServer(server);
44 | manifestParser.writeDevBuild(server.config.server.port!);
45 | });
46 | },
47 |
48 | async options(options) {
49 | manifestParser = ManifestParserFactory.getParser(
50 | pluginOptions,
51 | viteConfig
52 | );
53 |
54 | const { inputScripts, emitFiles } = await manifestParser.parseInput();
55 |
56 | options.input = addInputScriptsToOptionsInput(
57 | inputScripts,
58 | options.input
59 | );
60 |
61 | emitQueue = emitQueue.concat(emitFiles);
62 |
63 | return options;
64 | },
65 |
66 | buildStart() {
67 | emitQueue.forEach((file) => {
68 | this.emitFile(file);
69 |
70 | const fileName =
71 | file.type === "prebuilt-chunk"
72 | ? file.fileName
73 | : file.fileName ?? file.name!;
74 |
75 | this.addWatchFile(fileName);
76 | });
77 | emitQueue = [];
78 | },
79 |
80 | resolveId(id) {
81 | return getVirtualModule(id) ? id : null;
82 | },
83 |
84 | load(id) {
85 | return getVirtualModule(id);
86 | },
87 |
88 | transform(code) {
89 | return transformSelfLocationAssets(code, viteConfig);
90 | },
91 |
92 | async generateBundle(_options, bundle) {
93 | const { emitFiles } = await manifestParser.parseOutput(
94 | bundle as OutputBundle
95 | );
96 |
97 | emitFiles.forEach(this.emitFile);
98 | },
99 | };
100 | }
101 |
--------------------------------------------------------------------------------
/src/manifestParser/manifestParserFactory.ts:
--------------------------------------------------------------------------------
1 | import type { ResolvedConfig } from "vite";
2 | import { ViteWebExtensionOptions } from "../../types";
3 | import ManifestParser from "./manifestParser";
4 | import ManifestV2 from "./manifestV2";
5 | import ManifestV3 from "./manifestV3";
6 |
7 | export default class ManifestParserFactory {
8 | static getParser(
9 | pluginOptions: ViteWebExtensionOptions,
10 | viteConfig: ResolvedConfig
11 | ):
12 | | ManifestParser
13 | | ManifestParser {
14 | switch (pluginOptions.manifest.manifest_version) {
15 | case 2:
16 | return new ManifestV2(pluginOptions, viteConfig);
17 | case 3:
18 | return new ManifestV3(pluginOptions, viteConfig);
19 | default:
20 | throw new Error(
21 | `No parser available for manifest_version ${
22 | // @ts-expect-error - Allow showing manifest version for invalid usage
23 | manifest.manifest_version ?? 0
24 | }`
25 | );
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/manifestParser/manifestV2.ts:
--------------------------------------------------------------------------------
1 | import type { OutputBundle } from "rollup";
2 | import { ViteWebExtensionOptions } from "../../types";
3 | import DevBuilderManifestV2 from "../devBuilder/devBuilderManifestV2";
4 | import getNormalizedAdditionalInput from "../utils/getNormalizedAdditionalInput";
5 | import DevBuilder from "./../devBuilder/devBuilder";
6 | import ManifestParser, { ParseResult } from "./manifestParser";
7 |
8 | type Manifest = chrome.runtime.ManifestV2;
9 | type ManifestParseResult = ParseResult;
10 |
11 | export default class ManifestV2 extends ManifestParser {
12 | protected createDevBuilder(): DevBuilder {
13 | return new DevBuilderManifestV2(
14 | this.viteConfig,
15 | this.pluginOptions,
16 | this.viteDevServer,
17 | this.inputManifest
18 | );
19 | }
20 |
21 | protected getHtmlFileNames(manifest: Manifest): string[] {
22 | return [
23 | manifest.background?.page,
24 | manifest.browser_action?.default_popup,
25 | manifest.options_ui?.page,
26 | manifest.devtools_page,
27 | manifest.chrome_url_overrides?.newtab,
28 | manifest.chrome_url_overrides?.history,
29 | manifest.chrome_url_overrides?.bookmarks,
30 | ]
31 | .filter((fileName): fileName is string => typeof fileName === "string")
32 | .map((fileName) => fileName.split(/[\?\#]/)[0]);
33 | }
34 |
35 | protected getParseInputMethods(): ((
36 | result: ManifestParseResult
37 | ) => ManifestParseResult)[] {
38 | return [];
39 | }
40 |
41 | protected getParseOutputMethods(): ((
42 | result: ManifestParseResult
43 | ) => Promise)[] {
44 | return [];
45 | }
46 |
47 | protected async parseOutputContentScripts(
48 | result: ManifestParseResult,
49 | bundle: OutputBundle
50 | ): Promise {
51 | const webAccessibleResources = new Set(
52 | result.manifest.web_accessible_resources ?? []
53 | );
54 |
55 | result.manifest.content_scripts?.forEach((script) => {
56 | script.js?.forEach((scriptFileName, index) => {
57 | const parsedContentScript = this.parseOutputContentScript(
58 | scriptFileName,
59 | result,
60 | bundle
61 | );
62 |
63 | script.js![index] = parsedContentScript.fileName;
64 |
65 | parsedContentScript.webAccessibleFiles.forEach(
66 | webAccessibleResources.add,
67 | webAccessibleResources
68 | );
69 | });
70 |
71 | script.css?.forEach((cssFileName, index) => {
72 | const parsedContentCss = this.parseOutputContentCss(
73 | cssFileName,
74 | bundle
75 | );
76 |
77 | script.css![index] = parsedContentCss.cssFileName;
78 | });
79 | });
80 |
81 | if (webAccessibleResources.size > 0) {
82 | result.manifest.web_accessible_resources = Array.from(
83 | webAccessibleResources
84 | );
85 | }
86 |
87 | return result;
88 | }
89 |
90 | protected async parseOutputAdditionalInputs(
91 | result: ManifestParseResult,
92 | bundle: OutputBundle
93 | ): Promise {
94 | if (!this.pluginOptions.additionalInputs) {
95 | return result;
96 | }
97 |
98 | for (const [type, inputs] of Object.entries(
99 | this.pluginOptions.additionalInputs
100 | )) {
101 | for (const input of inputs) {
102 | const additionalInput = getNormalizedAdditionalInput(input);
103 |
104 | const parsedFile = this.parseOutputAdditionalInput(
105 | type as keyof NonNullable<
106 | ViteWebExtensionOptions["additionalInputs"]
107 | >,
108 | additionalInput,
109 | result,
110 | bundle
111 | );
112 |
113 | if (parsedFile.webAccessibleFiles.size) {
114 | result.manifest.web_accessible_resources = [
115 | ...(result.manifest.web_accessible_resources ?? []),
116 | ...parsedFile.webAccessibleFiles,
117 | ];
118 | }
119 | }
120 | }
121 |
122 | return result;
123 | }
124 |
125 | protected optimizeWebAccessibleResources(
126 | result: ParseResult
127 | ): ParseResult {
128 | if (!result.manifest.web_accessible_resources) {
129 | return result;
130 | }
131 |
132 | result.manifest.web_accessible_resources =
133 | result.manifest.web_accessible_resources.sort();
134 |
135 | return result;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/middleware/viteClientModifier.ts:
--------------------------------------------------------------------------------
1 | import getEtag from "etag";
2 | import type { Connect } from "vite";
3 |
4 | // Modifies the vite HMR client to support various web extension features including:
5 | // Exporting a function to add HMR style injection targets
6 | // Tweaks to support running in a service worker context
7 | const viteClientModifier: Connect.NextHandleFunction = (req, res, next) => {
8 | const _originalEnd = res.end;
9 |
10 | // @ts-ignore
11 | res.end = function end(chunk, ...otherArgs) {
12 | if (req.url === "/@vite/client" && typeof chunk === "string") {
13 | chunk = addCustomStyleFunctionality(chunk);
14 | chunk = addServiceWorkerSupport(chunk);
15 |
16 | res.setHeader("Etag", getEtag(chunk, { weak: true }));
17 | }
18 |
19 | // @ts-ignore
20 | return _originalEnd.call(this, chunk, ...otherArgs);
21 | };
22 |
23 | next();
24 | };
25 |
26 | function addCustomStyleFunctionality(source: string): string {
27 | if (
28 | !/const sheetsMap/.test(source) ||
29 | !/document\.head\.appendChild\(style\)/.test(source) ||
30 | !/document\.head\.removeChild\(style\)/.test(source) ||
31 | (!/style\.textContent = content/.test(source) &&
32 | !/style\.innerHTML = content/.test(source))
33 | ) {
34 | console.error(
35 | "Web extension HMR style support disabled -- failed to update vite client"
36 | );
37 |
38 | return source;
39 | }
40 |
41 | source = source.replace(
42 | "const sheetsMap",
43 | "const styleTargets = new Set(); const styleTargetsStyleMap = new Map(); const sheetsMap"
44 | );
45 | source = source.replace("export {", "export { addStyleTarget, ");
46 | source = source.replace(
47 | "document.head.appendChild(style)",
48 | "styleTargets.size ? styleTargets.forEach(target => addStyleToTarget(style, target)) : document.head.appendChild(style)"
49 | );
50 | source = source.replace(
51 | "document.head.removeChild(style)",
52 | "styleTargetsStyleMap.get(style) ? styleTargetsStyleMap.get(style).forEach(style => style.parentNode.removeChild(style)) : document.head.removeChild(style)"
53 | );
54 |
55 | const styleProperty = /style\.textContent = content/.test(source)
56 | ? "style.textContent"
57 | : "style.innerHTML";
58 |
59 | const lastStyleInnerHtml = source.lastIndexOf(`${styleProperty} = content`);
60 |
61 | source =
62 | source.slice(0, lastStyleInnerHtml) +
63 | source
64 | .slice(lastStyleInnerHtml)
65 | .replace(
66 | `${styleProperty} = content`,
67 | `${styleProperty} = content; styleTargetsStyleMap.get(style)?.forEach(style => ${styleProperty} = content)`
68 | );
69 |
70 | source += `
71 | function addStyleTarget(newStyleTarget) {
72 | for (const [, style] of sheetsMap.entries()) {
73 | addStyleToTarget(style, newStyleTarget, styleTargets.size !== 0);
74 | }
75 |
76 | styleTargets.add(newStyleTarget);
77 | }
78 |
79 | function addStyleToTarget(style, target, cloneStyle = true) {
80 | const addedStyle = cloneStyle ? style.cloneNode(true) : style;
81 | target.appendChild(addedStyle);
82 |
83 | styleTargetsStyleMap.set(style, [...(styleTargetsStyleMap.get(style) ?? []), addedStyle]);
84 | }
85 | `;
86 |
87 | return source;
88 | }
89 |
90 | function guardDocumentUsageWithDefault(
91 | source: string,
92 | documentUsage: string,
93 | defaultValue: string
94 | ): string {
95 | return source.replace(
96 | documentUsage,
97 | `('document' in globalThis ? ${documentUsage} : ${defaultValue})`
98 | );
99 | }
100 |
101 | function addServiceWorkerSupport(source: string): string {
102 | // update location.reload usages
103 | source = source.replaceAll(
104 | /(window\.)?location.reload\(\)/g,
105 | "(location.reload?.() ?? (typeof chrome !== 'undefined' ? chrome.runtime?.reload?.() : ''))"
106 | );
107 |
108 | // add document guards
109 | source = guardDocumentUsageWithDefault(
110 | source,
111 | "document.querySelectorAll(overlayId).length",
112 | "false"
113 | );
114 |
115 | source = guardDocumentUsageWithDefault(
116 | source,
117 | "document.visibilityState",
118 | `"visible"`
119 | );
120 |
121 | source = guardDocumentUsageWithDefault(
122 | source,
123 | `document.querySelectorAll('link')`,
124 | "[]"
125 | );
126 |
127 | source = source.replace(
128 | "const enableOverlay =",
129 | `const enableOverlay = ('document' in globalThis) &&`
130 | );
131 |
132 | return source;
133 | }
134 |
135 | export default viteClientModifier;
136 |
--------------------------------------------------------------------------------
/src/utils/addHmrSupportToCsp.ts:
--------------------------------------------------------------------------------
1 | import parse from "content-security-policy-parser";
2 |
3 | export const addHmrSupportToCsp = (
4 | hmrServerOrigin: string,
5 | inlineScriptHashes: Set,
6 | contentSecurityPolicyStr?: string | undefined
7 | ): string => {
8 | const inlineScriptHashesArr = Array.from(inlineScriptHashes);
9 | const scriptSrcs = ["'self'", hmrServerOrigin].concat(
10 | inlineScriptHashesArr || []
11 | );
12 |
13 | const contentSecurityPolicy = parse(contentSecurityPolicyStr || "");
14 | contentSecurityPolicy["script-src"] = scriptSrcs.concat(
15 | contentSecurityPolicy["script-src"]
16 | );
17 | contentSecurityPolicy["object-src"] = ["'self'"].concat(
18 | contentSecurityPolicy["object-src"]
19 | );
20 |
21 | return Object.keys(contentSecurityPolicy)
22 | .map((key) => {
23 | return (
24 | `${key} ` +
25 | contentSecurityPolicy[key]
26 | .filter((c, idx) => contentSecurityPolicy[key].indexOf(c) === idx) // Dedupe
27 | .join(" ")
28 | );
29 | })
30 | .join("; ");
31 | };
32 |
--------------------------------------------------------------------------------
/src/utils/file.ts:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 | import { normalizePath } from "vite";
3 |
4 | export function getNormalizedFileName(
5 | fileName: string,
6 | includeExt = true
7 | ): string {
8 | let { dir, name, ext } = path.parse(normalizePath(path.normalize(fileName)));
9 |
10 | if (!dir) {
11 | return `${name}${includeExt ? ext : ""}`;
12 | }
13 |
14 | dir = dir.startsWith("/") ? dir.slice(1) : dir;
15 |
16 | return `${dir}/${name}${includeExt ? ext : ""}`;
17 | }
18 |
19 | export function getInputFileName(inputFileName: string, root: string): string {
20 | return `${root}/${getNormalizedFileName(inputFileName, true)}`;
21 | }
22 |
23 | export function getOutputFileName(inputFileName: string): string {
24 | return getNormalizedFileName(inputFileName, false);
25 | }
26 |
--------------------------------------------------------------------------------
/src/utils/getAdditionalInputAsWebAccessibleResource.ts:
--------------------------------------------------------------------------------
1 | import { NormalizedAdditionalInput } from "../../types";
2 |
3 | export default function getAdditionalInputAsWebAccessibleResource(
4 | input: NormalizedAdditionalInput
5 | ): {
6 | matches: string[] | undefined;
7 | extension_ids: string[] | undefined;
8 | use_dynamic_url?: boolean;
9 | } | null {
10 | if (!input.webAccessible) {
11 | return null;
12 | }
13 |
14 | return {
15 | matches: input.webAccessible.matches,
16 | extension_ids: input.webAccessible.extensionIds,
17 | use_dynamic_url: true,
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/src/utils/getNormalizedAdditionalInput.ts:
--------------------------------------------------------------------------------
1 | import { AdditionalInput, NormalizedAdditionalInput } from "../../types";
2 |
3 | export default function getNormalizedAdditionalInput(
4 | input: AdditionalInput
5 | ): NormalizedAdditionalInput {
6 | const webAccessibleDefaults = {
7 | matches: [""],
8 | excludeEntryFile: false,
9 | };
10 |
11 | if (typeof input === "string") {
12 | return {
13 | fileName: input,
14 | webAccessible: webAccessibleDefaults,
15 | };
16 | }
17 |
18 | if (typeof input.webAccessible === "boolean") {
19 | return {
20 | ...input,
21 | webAccessible: input.webAccessible ? webAccessibleDefaults : null,
22 | };
23 | }
24 |
25 | return {
26 | ...input,
27 | webAccessible: {
28 | excludeEntryFile: webAccessibleDefaults.excludeEntryFile,
29 | ...input.webAccessible,
30 | },
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/src/utils/loader.ts:
--------------------------------------------------------------------------------
1 | import type { OutputChunk } from "rollup";
2 | import { getOutputFileName } from "./file";
3 |
4 | export function getScriptHtmlLoaderFile(name: string, scriptSrcs: string[]) {
5 | const scriptsHtml = scriptSrcs
6 | .map((scriptSrc) => {
7 | return ``;
8 | })
9 | .join("");
10 |
11 | return {
12 | fileName: `${name}.html`,
13 | source: `${scriptsHtml}`,
14 | };
15 | }
16 |
17 | export function getScriptLoaderFile(
18 | scriptFileName: string,
19 | inputFileNames: string[]
20 | ): {
21 | fileName: string;
22 | source: string;
23 | } {
24 | const outputFile = getOutputFileName(scriptFileName);
25 |
26 | const importStatements = inputFileNames
27 | .filter((fileName) => Boolean(fileName))
28 | .map((fileName) => {
29 | return fileName.startsWith("http")
30 | ? `"${fileName}"`
31 | : `chrome.runtime.getURL("${fileName}")`;
32 | })
33 | .map((importPath) => `await import(${importPath})`)
34 | .join(";");
35 |
36 | return {
37 | fileName: `${outputFile}.js`,
38 | source: `(async()=>{${importStatements}})();`,
39 | };
40 | }
41 |
42 | export function getServiceWorkerLoaderFile(inputFileNames: string[]) {
43 | const importStatements = inputFileNames
44 | .filter((fileName) => Boolean(fileName))
45 | .map((fileName) => {
46 | return fileName.startsWith("http") ? fileName : `/${fileName}`;
47 | })
48 | .map((importPath) => `import "${importPath}";`)
49 | .join("\n");
50 |
51 | return {
52 | fileName: `serviceWorker.js`,
53 | source: importStatements,
54 | };
55 | }
56 |
57 | export function getScriptLoaderForOutputChunk(
58 | contentScriptFileName: string,
59 | chunk: OutputChunk
60 | ): { fileName: string; source: string } | null {
61 | if (!chunk.imports.length && !chunk.dynamicImports.length) {
62 | return null;
63 | }
64 |
65 | return getScriptLoaderFile(contentScriptFileName, [chunk.fileName]);
66 | }
67 |
--------------------------------------------------------------------------------
/src/utils/rollup.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | InputOptions,
3 | OutputAsset,
4 | OutputBundle,
5 | OutputChunk,
6 | } from "rollup";
7 | import { ViteWebExtensionOptions } from "../../types";
8 | import { getNormalizedFileName } from "./file";
9 |
10 | export function addInputScriptsToOptionsInput(
11 | inputScripts: [string, string][],
12 | optionsInput: InputOptions["input"]
13 | ): { [entryAlias: string]: string } {
14 | const optionsInputObject = getOptionsInputAsObject(optionsInput);
15 |
16 | inputScripts.forEach(([output, input]) => {
17 | input = input.trim();
18 |
19 | if (
20 | optionsInputObject[output] &&
21 | optionsInputObject[output].trim() !== input
22 | ) {
23 | throw new Error(
24 | `Inputs (${optionsInputObject[output]}) and (${input}) share an output identifier of (${output}). Rename one of the inputs to prevent output resolution issues.`
25 | );
26 | }
27 |
28 | optionsInputObject[output] = input;
29 | });
30 |
31 | return optionsInputObject;
32 | }
33 |
34 | function getOptionsInputAsObject(input: InputOptions["input"]): {
35 | [entryAlias: string]: string;
36 | } {
37 | if (typeof input === "string") {
38 | if (!input.trim()) {
39 | return {};
40 | }
41 |
42 | return {
43 | [input]: input,
44 | };
45 | } else if (input instanceof Array) {
46 | if (!input.length) {
47 | return {};
48 | }
49 |
50 | const inputObject: { [entryAlias: string]: string } = {};
51 |
52 | input.forEach((input) => (inputObject[input] = input));
53 |
54 | return inputObject;
55 | }
56 |
57 | return input ?? {};
58 | }
59 |
60 | export function getChunkInfoFromBundle(
61 | bundle: OutputBundle,
62 | chunkId: string
63 | ): OutputChunk | undefined {
64 | const normalizedId = getNormalizedFileName(chunkId);
65 |
66 | return Object.values(bundle).find((chunk) => {
67 | if (chunk.type === "asset") {
68 | return false;
69 | }
70 |
71 | return (
72 | chunk.facadeModuleId?.endsWith(normalizedId) ||
73 | chunk.fileName.endsWith(normalizedId)
74 | );
75 | }) as OutputChunk | undefined;
76 | }
77 |
78 | function findMatchingOutputAsset(
79 | bundle: OutputBundle,
80 | normalizedInputId: string
81 | ): OutputAsset | undefined {
82 | return Object.values(bundle).find((chunk) => {
83 | if (chunk.type === "chunk") {
84 | return;
85 | }
86 |
87 | if (chunk.name) {
88 | return normalizedInputId.endsWith(chunk.name);
89 | }
90 |
91 | return chunk.fileName.endsWith(normalizedInputId);
92 | }) as OutputAsset | undefined;
93 | }
94 |
95 | export function getOutputInfoFromBundle(
96 | type: keyof NonNullable,
97 | bundle: OutputBundle,
98 | inputId: string
99 | ): OutputAsset | OutputChunk | undefined {
100 | switch (type) {
101 | case "styles":
102 | return getCssAssetInfoFromBundle(bundle, inputId);
103 | case "scripts":
104 | return getChunkInfoFromBundle(bundle, inputId);
105 | case "html":
106 | return findMatchingOutputAsset(bundle, inputId);
107 | default:
108 | throw new Error(`Invalid additionalInput type of ${type}`);
109 | }
110 | }
111 |
112 | export function getCssAssetInfoFromBundle(
113 | bundle: OutputBundle,
114 | assetFileName: string
115 | ): OutputAsset | undefined {
116 | const normalizedInputId = getNormalizedFileName(assetFileName, false);
117 |
118 | return findMatchingOutputAsset(bundle, `${normalizedInputId}.css`);
119 | }
120 |
--------------------------------------------------------------------------------
/src/utils/virtualModule.ts:
--------------------------------------------------------------------------------
1 | const virtualModules = new Map();
2 |
3 | export function setVirtualModule(id: string, source: string) {
4 | virtualModules.set(id, source);
5 | }
6 |
7 | export function getVirtualModule(id: string): string | null {
8 | return virtualModules.get(id) ?? null;
9 | }
10 |
--------------------------------------------------------------------------------
/src/utils/vite.ts:
--------------------------------------------------------------------------------
1 | import MagicString from "magic-string";
2 | import type { Manifest, ManifestChunk, ResolvedConfig, UserConfig } from "vite";
3 | import { getNormalizedFileName } from "./file";
4 |
5 | // Update vite user config with settings necessary for the plugin to work
6 | export function updateConfigForExtensionSupport(
7 | config: UserConfig,
8 | manifest: chrome.runtime.Manifest
9 | ): UserConfig {
10 | config.build ??= {};
11 |
12 | if (!config.build.target) {
13 | switch (manifest.manifest_version) {
14 | case 2:
15 | config.build.target = ["chrome64", "firefox89"]; // minimum browsers with import.meta.url and content script dynamic import
16 | break;
17 | case 3:
18 | config.build.target = ["chrome91"];
19 | break;
20 | }
21 | }
22 |
23 | config.build.modulePreload ??= false;
24 |
25 | config.build.rollupOptions ??= {};
26 | config.build.rollupOptions.input ??= {};
27 |
28 | config.optimizeDeps ??= {};
29 | config.optimizeDeps.exclude = [
30 | ...(config.optimizeDeps.exclude ?? []),
31 | "/@vite/client",
32 | ];
33 |
34 | config.server ??= {};
35 |
36 | if (config.server.hmr === true || !config.server.hmr) {
37 | config.server.hmr = {};
38 | }
39 |
40 | config.server.hmr.protocol = "ws"; // required for content script hmr to work on https
41 | config.server.hmr.host = "localhost";
42 |
43 | return config;
44 | }
45 |
46 | // Vite asset helper rewrites usages of import.meta.url to self.location for broader
47 | // browser support, but content scripts need to reference assets via import.meta.url
48 | // This transform rewrites self.location back to import.meta.url
49 | export function transformSelfLocationAssets(
50 | code: string,
51 | resolvedViteConfig: ResolvedConfig
52 | ) {
53 | if (code.includes("new URL") && code.includes(`self.location`)) {
54 | let updatedCode: MagicString | null = null;
55 | const selfLocationUrlPattern =
56 | /\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*self\.location\s*\)/g;
57 |
58 | let match: RegExpExecArray | null;
59 | while ((match = selfLocationUrlPattern.exec(code))) {
60 | const { 0: exp, index } = match;
61 |
62 | if (!updatedCode) updatedCode = new MagicString(code);
63 |
64 | updatedCode.overwrite(
65 | index,
66 | index + exp.length,
67 | exp.replace("self.location", "import.meta.url")
68 | );
69 | }
70 |
71 | if (updatedCode) {
72 | return {
73 | code: updatedCode.toString(),
74 | map: resolvedViteConfig.build.sourcemap
75 | ? updatedCode.generateMap({ hires: true })
76 | : null,
77 | };
78 | }
79 | }
80 |
81 | return null;
82 | }
83 |
84 | export function findChunkInManifestByFileName(
85 | manifest: Manifest,
86 | fileName: string
87 | ): ManifestChunk | undefined {
88 | return manifest[getNormalizedFileName(fileName)];
89 | }
90 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsHtml.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsHtml - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "assets/html.css",
7 | "name": "html.css",
8 | "source": "body {
9 | color: red;
10 | }
11 | ",
12 | "type": "asset",
13 | },
14 | {
15 | "code": "function log(message) {
16 | console.log(message);
17 | }
18 | log("webAccessible");
19 | ",
20 | "dynamicImports": [],
21 | "exports": [],
22 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/additionalInputsHtml/html.html",
23 | "fileName": "assets/test/manifest/resources/additionalInputsHtml/html.js",
24 | "implicitlyLoadedBefore": [],
25 | "importedBindings": {},
26 | "imports": [],
27 | "isDynamicEntry": false,
28 | "isEntry": true,
29 | "isImplicitEntry": false,
30 | "map": null,
31 | "modules": {
32 | "vite-plugin-web-extension/test/manifest/resources/additionalInputsHtml/html.html": {
33 | "code": "",
34 | "originalLength": 290,
35 | "removedExports": [],
36 | "renderedExports": [],
37 | "renderedLength": 0,
38 | },
39 | "vite-plugin-web-extension/test/manifest/resources/additionalInputsHtml/script.js": {
40 | "code": "log("webAccessible");",
41 | "originalLength": 58,
42 | "removedExports": [],
43 | "renderedExports": [],
44 | "renderedLength": 21,
45 | },
46 | "vite-plugin-web-extension/test/manifest/resources/additionalInputsHtml/style.css": {
47 | "code": "",
48 | "originalLength": 23,
49 | "removedExports": [],
50 | "renderedExports": [],
51 | "renderedLength": 0,
52 | },
53 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
54 | "code": "function log(message) {
55 | console.log(message);
56 | }",
57 | "originalLength": 65,
58 | "removedExports": [],
59 | "renderedExports": [
60 | "default",
61 | ],
62 | "renderedLength": 49,
63 | },
64 | },
65 | "name": "test/manifest/resources/additionalInputsHtml/html",
66 | "referencedFiles": [],
67 | "type": "chunk",
68 | "viteMetadata": {
69 | "importedAssets": Set {},
70 | "importedCss": Set {
71 | "assets/html.css",
72 | },
73 | },
74 | },
75 | {
76 | "fileName": "manifest.json",
77 | "name": undefined,
78 | "source": "{
79 | "version": "1.0.0",
80 | "name": "Manifest Name",
81 | "manifest_version": 2,
82 | "web_accessible_resources": [
83 | "test/manifest/resources/additionalInputsHtml/html.html"
84 | ]
85 | }",
86 | "type": "asset",
87 | },
88 | {
89 | "fileName": "test/manifest/resources/additionalInputsHtml/html.html",
90 | "name": undefined,
91 | "source": "
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | ",
102 | "type": "asset",
103 | },
104 | ]
105 | `;
106 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsHtml.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsHtml - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "assets/html.css",
7 | "name": "html.css",
8 | "source": "body {
9 | color: red;
10 | }
11 | ",
12 | "type": "asset",
13 | },
14 | {
15 | "code": "function log(message) {
16 | console.log(message);
17 | }
18 | log("webAccessible");
19 | ",
20 | "dynamicImports": [],
21 | "exports": [],
22 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/additionalInputsHtml/html.html",
23 | "fileName": "assets/test/manifest/resources/additionalInputsHtml/html.js",
24 | "implicitlyLoadedBefore": [],
25 | "importedBindings": {},
26 | "imports": [],
27 | "isDynamicEntry": false,
28 | "isEntry": true,
29 | "isImplicitEntry": false,
30 | "map": null,
31 | "modules": {
32 | "vite-plugin-web-extension/test/manifest/resources/additionalInputsHtml/html.html": {
33 | "code": "",
34 | "originalLength": 290,
35 | "removedExports": [],
36 | "renderedExports": [],
37 | "renderedLength": 0,
38 | },
39 | "vite-plugin-web-extension/test/manifest/resources/additionalInputsHtml/script.js": {
40 | "code": "log("webAccessible");",
41 | "originalLength": 58,
42 | "removedExports": [],
43 | "renderedExports": [],
44 | "renderedLength": 21,
45 | },
46 | "vite-plugin-web-extension/test/manifest/resources/additionalInputsHtml/style.css": {
47 | "code": "",
48 | "originalLength": 23,
49 | "removedExports": [],
50 | "renderedExports": [],
51 | "renderedLength": 0,
52 | },
53 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
54 | "code": "function log(message) {
55 | console.log(message);
56 | }",
57 | "originalLength": 65,
58 | "removedExports": [],
59 | "renderedExports": [
60 | "default",
61 | ],
62 | "renderedLength": 49,
63 | },
64 | },
65 | "name": "test/manifest/resources/additionalInputsHtml/html",
66 | "referencedFiles": [],
67 | "type": "chunk",
68 | "viteMetadata": {
69 | "importedAssets": Set {},
70 | "importedCss": Set {
71 | "assets/html.css",
72 | },
73 | },
74 | },
75 | {
76 | "fileName": "manifest.json",
77 | "name": undefined,
78 | "source": "{
79 | "version": "1.0.0",
80 | "name": "Manifest Name",
81 | "manifest_version": 3,
82 | "web_accessible_resources": [
83 | {
84 | "resources": [
85 | "test/manifest/resources/additionalInputsHtml/html.html"
86 | ],
87 | "matches": [
88 | ""
89 | ]
90 | }
91 | ]
92 | }",
93 | "type": "asset",
94 | },
95 | {
96 | "fileName": "test/manifest/resources/additionalInputsHtml/html.html",
97 | "name": undefined,
98 | "source": "
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | ",
109 | "type": "asset",
110 | },
111 | ]
112 | `;
113 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsScriptsChunkedImport.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsScriptsChunkedImport - Manifest V2 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | export {
10 | log as l
11 | };
12 | ",
13 | "dynamicImports": [],
14 | "exports": [
15 | "l",
16 | ],
17 | "facadeModuleId": null,
18 | "fileName": "assets/log.js",
19 | "implicitlyLoadedBefore": [],
20 | "importedBindings": {},
21 | "imports": [],
22 | "isDynamicEntry": false,
23 | "isEntry": false,
24 | "isImplicitEntry": false,
25 | "map": null,
26 | "modules": {
27 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
28 | "code": "function log(message) {
29 | console.log(message);
30 | }",
31 | "originalLength": 65,
32 | "removedExports": [],
33 | "renderedExports": [
34 | "default",
35 | ],
36 | "renderedLength": 49,
37 | },
38 | },
39 | "name": "log",
40 | "referencedFiles": [],
41 | "type": "chunk",
42 | "viteMetadata": {
43 | "importedAssets": Set {},
44 | "importedCss": Set {},
45 | },
46 | },
47 | {
48 | "code": "import { l as log } from "../../../../log.js";
49 | log("script1");
50 | ",
51 | "dynamicImports": [],
52 | "exports": [],
53 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/additionalInputsScriptsChunkedImport/script1.js",
54 | "fileName": "assets/test/manifest/resources/additionalInputsScriptsChunkedImport/script1.js",
55 | "implicitlyLoadedBefore": [],
56 | "importedBindings": {
57 | "assets/log.js": [
58 | "l",
59 | ],
60 | },
61 | "imports": [
62 | "assets/log.js",
63 | ],
64 | "isDynamicEntry": false,
65 | "isEntry": true,
66 | "isImplicitEntry": false,
67 | "map": null,
68 | "modules": {
69 | "vite-plugin-web-extension/test/manifest/resources/additionalInputsScriptsChunkedImport/script1.js": {
70 | "code": "log("script1");",
71 | "originalLength": 50,
72 | "removedExports": [],
73 | "renderedExports": [],
74 | "renderedLength": 15,
75 | },
76 | },
77 | "name": "test/manifest/resources/additionalInputsScriptsChunkedImport/script1",
78 | "referencedFiles": [],
79 | "type": "chunk",
80 | "viteMetadata": {
81 | "importedAssets": Set {},
82 | "importedCss": Set {},
83 | },
84 | },
85 | {
86 | "code": "import { l as log } from "../../../../log.js";
87 | log("script2");
88 | ",
89 | "dynamicImports": [],
90 | "exports": [],
91 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/additionalInputsScriptsChunkedImport/script2.js",
92 | "fileName": "assets/test/manifest/resources/additionalInputsScriptsChunkedImport/script2.js",
93 | "implicitlyLoadedBefore": [],
94 | "importedBindings": {
95 | "assets/log.js": [
96 | "l",
97 | ],
98 | },
99 | "imports": [
100 | "assets/log.js",
101 | ],
102 | "isDynamicEntry": false,
103 | "isEntry": true,
104 | "isImplicitEntry": false,
105 | "map": null,
106 | "modules": {
107 | "vite-plugin-web-extension/test/manifest/resources/additionalInputsScriptsChunkedImport/script2.js": {
108 | "code": "log("script2");",
109 | "originalLength": 50,
110 | "removedExports": [],
111 | "renderedExports": [],
112 | "renderedLength": 15,
113 | },
114 | },
115 | "name": "test/manifest/resources/additionalInputsScriptsChunkedImport/script2",
116 | "referencedFiles": [],
117 | "type": "chunk",
118 | "viteMetadata": {
119 | "importedAssets": Set {},
120 | "importedCss": Set {},
121 | },
122 | },
123 | {
124 | "fileName": "manifest.json",
125 | "name": undefined,
126 | "source": "{
127 | "version": "1.0.0",
128 | "name": "Manifest Name",
129 | "manifest_version": 2,
130 | "web_accessible_resources": [
131 | "assets/log.js",
132 | "assets/test/manifest/resources/additionalInputsScriptsChunkedImport/script1.js",
133 | "assets/test/manifest/resources/additionalInputsScriptsChunkedImport/script2.js",
134 | "test/manifest/resources/additionalInputsScriptsChunkedImport/script1.js",
135 | "test/manifest/resources/additionalInputsScriptsChunkedImport/script2.js"
136 | ]
137 | }",
138 | "type": "asset",
139 | },
140 | {
141 | "fileName": "test/manifest/resources/additionalInputsScriptsChunkedImport/script1.js",
142 | "name": undefined,
143 | "source": "(async()=>{await import(chrome.runtime.getURL("assets/test/manifest/resources/additionalInputsScriptsChunkedImport/script1.js"))})();",
144 | "type": "asset",
145 | },
146 | {
147 | "fileName": "test/manifest/resources/additionalInputsScriptsChunkedImport/script2.js",
148 | "name": undefined,
149 | "source": "(async()=>{await import(chrome.runtime.getURL("assets/test/manifest/resources/additionalInputsScriptsChunkedImport/script2.js"))})();",
150 | "type": "asset",
151 | },
152 | ]
153 | `;
154 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsScriptsNoImport.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsScriptsNoImport - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 2,
12 | "web_accessible_resources": [
13 | "test/manifest/resources/additionalInputsScriptsNoImport/script1.js",
14 | "test/manifest/resources/additionalInputsScriptsNoImport/script2.js"
15 | ]
16 | }",
17 | "type": "asset",
18 | },
19 | {
20 | "fileName": "test/manifest/resources/additionalInputsScriptsNoImport/script1.js",
21 | "name": undefined,
22 | "source": "console.log("script1");
23 | ",
24 | "type": "asset",
25 | },
26 | {
27 | "fileName": "test/manifest/resources/additionalInputsScriptsNoImport/script2.js",
28 | "name": undefined,
29 | "source": "console.log("script2");
30 | ",
31 | "type": "asset",
32 | },
33 | ]
34 | `;
35 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsScriptsNoImport.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsScriptsNoImport - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 3,
12 | "web_accessible_resources": [
13 | {
14 | "resources": [
15 | "test/manifest/resources/additionalInputsScriptsNoImport/script1.js",
16 | "test/manifest/resources/additionalInputsScriptsNoImport/script2.js"
17 | ],
18 | "matches": [
19 | ""
20 | ]
21 | }
22 | ]
23 | }",
24 | "type": "asset",
25 | },
26 | {
27 | "fileName": "test/manifest/resources/additionalInputsScriptsNoImport/script1.js",
28 | "name": undefined,
29 | "source": "console.log("script1");
30 | ",
31 | "type": "asset",
32 | },
33 | {
34 | "fileName": "test/manifest/resources/additionalInputsScriptsNoImport/script2.js",
35 | "name": undefined,
36 | "source": "console.log("script2");
37 | ",
38 | "type": "asset",
39 | },
40 | ]
41 | `;
42 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsScriptsTypes.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsScriptsTypes - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 2,
12 | "web_accessible_resources": [
13 | "test/manifest/resources/additionalInputsScriptsTypes/script1.js",
14 | "test/manifest/resources/additionalInputsScriptsTypes/script2.js"
15 | ]
16 | }",
17 | "type": "asset",
18 | },
19 | {
20 | "fileName": "test/manifest/resources/additionalInputsScriptsTypes/script1.js",
21 | "name": undefined,
22 | "source": "console.log("script1");
23 | ",
24 | "type": "asset",
25 | },
26 | {
27 | "fileName": "test/manifest/resources/additionalInputsScriptsTypes/script2.js",
28 | "name": undefined,
29 | "source": "console.log("script2");
30 | ",
31 | "type": "asset",
32 | },
33 | ]
34 | `;
35 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsScriptsTypes.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsScriptsTypes - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 3,
12 | "web_accessible_resources": [
13 | {
14 | "resources": [
15 | "test/manifest/resources/additionalInputsScriptsTypes/script1.js",
16 | "test/manifest/resources/additionalInputsScriptsTypes/script2.js"
17 | ],
18 | "matches": [
19 | ""
20 | ]
21 | }
22 | ]
23 | }",
24 | "type": "asset",
25 | },
26 | {
27 | "fileName": "test/manifest/resources/additionalInputsScriptsTypes/script1.js",
28 | "name": undefined,
29 | "source": "console.log("script1");
30 | ",
31 | "type": "asset",
32 | },
33 | {
34 | "fileName": "test/manifest/resources/additionalInputsScriptsTypes/script2.js",
35 | "name": undefined,
36 | "source": "console.log("script2");
37 | ",
38 | "type": "asset",
39 | },
40 | ]
41 | `;
42 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsScriptsUnchunkedImport.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsScriptsUnchunkedImport - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 2,
12 | "web_accessible_resources": [
13 | "test/manifest/resources/additionalInputsScriptsUnchunkedImport/script1.js",
14 | "test/manifest/resources/additionalInputsScriptsUnchunkedImport/script2.js"
15 | ]
16 | }",
17 | "type": "asset",
18 | },
19 | {
20 | "fileName": "test/manifest/resources/additionalInputsScriptsUnchunkedImport/script1.js",
21 | "name": undefined,
22 | "source": "function log(message) {
23 | console.log(message);
24 | }
25 | log("script1");
26 | ",
27 | "type": "asset",
28 | },
29 | {
30 | "fileName": "test/manifest/resources/additionalInputsScriptsUnchunkedImport/script2.js",
31 | "name": undefined,
32 | "source": "console.log("script2");
33 | ",
34 | "type": "asset",
35 | },
36 | ]
37 | `;
38 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsScriptsUnchunkedImport.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsScriptsUnchunkedImport - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 3,
12 | "web_accessible_resources": [
13 | {
14 | "resources": [
15 | "test/manifest/resources/additionalInputsScriptsUnchunkedImport/script1.js",
16 | "test/manifest/resources/additionalInputsScriptsUnchunkedImport/script2.js"
17 | ],
18 | "matches": [
19 | ""
20 | ]
21 | }
22 | ]
23 | }",
24 | "type": "asset",
25 | },
26 | {
27 | "fileName": "test/manifest/resources/additionalInputsScriptsUnchunkedImport/script1.js",
28 | "name": undefined,
29 | "source": "function log(message) {
30 | console.log(message);
31 | }
32 | log("script1");
33 | ",
34 | "type": "asset",
35 | },
36 | {
37 | "fileName": "test/manifest/resources/additionalInputsScriptsUnchunkedImport/script2.js",
38 | "name": undefined,
39 | "source": "console.log("script2");
40 | ",
41 | "type": "asset",
42 | },
43 | ]
44 | `;
45 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsStylesTypes.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsStylesTypes - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 2,
12 | "web_accessible_resources": [
13 | "test/manifest/resources/additionalInputsStylesTypes/style1.css",
14 | "test/manifest/resources/additionalInputsStylesTypes/style2.css"
15 | ]
16 | }",
17 | "type": "asset",
18 | },
19 | {
20 | "fileName": "test/manifest/resources/additionalInputsStylesTypes/style1.css",
21 | "name": undefined,
22 | "source": "body {
23 | color: red;
24 | }
25 | ",
26 | "type": "asset",
27 | },
28 | {
29 | "fileName": "test/manifest/resources/additionalInputsStylesTypes/style2.css",
30 | "name": undefined,
31 | "source": "body {
32 | color: green;
33 | }",
34 | "type": "asset",
35 | },
36 | ]
37 | `;
38 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/additionalInputsStylesTypes.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`additionalInputsStylesTypes - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 3,
12 | "web_accessible_resources": [
13 | {
14 | "resources": [
15 | "test/manifest/resources/additionalInputsStylesTypes/style1.css",
16 | "test/manifest/resources/additionalInputsStylesTypes/style2.css"
17 | ],
18 | "matches": [
19 | ""
20 | ]
21 | }
22 | ]
23 | }",
24 | "type": "asset",
25 | },
26 | {
27 | "fileName": "test/manifest/resources/additionalInputsStylesTypes/style1.css",
28 | "name": undefined,
29 | "source": "body {
30 | color: red;
31 | }
32 | ",
33 | "type": "asset",
34 | },
35 | {
36 | "fileName": "test/manifest/resources/additionalInputsStylesTypes/style2.css",
37 | "name": undefined,
38 | "source": "body {
39 | color: green;
40 | }",
41 | "type": "asset",
42 | },
43 | ]
44 | `;
45 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/backgroundHtml.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`backgroundHtml - Manifest V2 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("background");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/backgroundHtml/background.html",
14 | "fileName": "assets/test/manifest/resources/backgroundHtml/background.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/backgroundHtml/background.html": {
24 | "code": "",
25 | "originalLength": 229,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 0,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/backgroundHtml/background.js": {
31 | "code": "log("background");",
32 | "originalLength": 55,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 18,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/backgroundHtml/background",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 2,
64 | "background": {
65 | "page": "test/manifest/resources/backgroundHtml/background.html",
66 | "persistent": false
67 | }
68 | }",
69 | "type": "asset",
70 | },
71 | {
72 | "fileName": "test/manifest/resources/backgroundHtml/background.html",
73 | "name": undefined,
74 | "source": "
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | ",
84 | "type": "asset",
85 | },
86 | ]
87 | `;
88 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/backgroundScript.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`backgroundScript - Manifest V2 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("background");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/background.html",
14 | "fileName": "assets/background.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/background.html": {
24 | "code": "",
25 | "originalLength": 168,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 0,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/backgroundScript/background.js": {
31 | "code": "log("background");",
32 | "originalLength": 55,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 18,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "background",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "background.html",
59 | "name": undefined,
60 | "source": "
61 | ",
62 | "type": "asset",
63 | },
64 | {
65 | "fileName": "manifest.json",
66 | "name": undefined,
67 | "source": "{
68 | "version": "1.0.0",
69 | "name": "Manifest Name",
70 | "manifest_version": 2,
71 | "background": {
72 | "persistent": false,
73 | "page": "background.html"
74 | }
75 | }",
76 | "type": "asset",
77 | },
78 | ]
79 | `;
80 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/backgroundServiceWorker.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`backgroundServiceWorker - Manifest V3 1`] = `
4 | [
5 | {
6 | "code": "console.log("serviceWorker");
7 | ",
8 | "dynamicImports": [],
9 | "exports": [],
10 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/backgroundServiceWorker/serviceWorker.js",
11 | "fileName": "assets/test/manifest/resources/backgroundServiceWorker/serviceWorker.js",
12 | "implicitlyLoadedBefore": [],
13 | "importedBindings": {},
14 | "imports": [],
15 | "isDynamicEntry": false,
16 | "isEntry": true,
17 | "isImplicitEntry": false,
18 | "map": null,
19 | "modules": {
20 | "vite-plugin-web-extension/test/manifest/resources/backgroundServiceWorker/serviceWorker.js": {
21 | "code": "console.log("serviceWorker");",
22 | "originalLength": 30,
23 | "removedExports": [],
24 | "renderedExports": [],
25 | "renderedLength": 29,
26 | },
27 | },
28 | "name": "test/manifest/resources/backgroundServiceWorker/serviceWorker",
29 | "referencedFiles": [],
30 | "type": "chunk",
31 | "viteMetadata": {
32 | "importedAssets": Set {},
33 | "importedCss": Set {},
34 | },
35 | },
36 | {
37 | "fileName": "manifest.json",
38 | "name": undefined,
39 | "source": "{
40 | "version": "1.0.0",
41 | "name": "Manifest Name",
42 | "manifest_version": 3,
43 | "background": {
44 | "service_worker": "serviceWorker.js",
45 | "type": "module"
46 | }
47 | }",
48 | "type": "asset",
49 | },
50 | {
51 | "fileName": "serviceWorker.js",
52 | "name": undefined,
53 | "source": "import "/assets/test/manifest/resources/backgroundServiceWorker/serviceWorker.js";",
54 | "type": "asset",
55 | },
56 | ]
57 | `;
58 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/backgroundServiceWorkerRelative.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`backgroundServiceWorker - Manifest V3 1`] = `
4 | [
5 | {
6 | "code": "console.log("serviceWorker");
7 | ",
8 | "dynamicImports": [],
9 | "exports": [],
10 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/backgroundServiceWorker/serviceWorker.js",
11 | "fileName": "assets/test/manifest/resources/backgroundServiceWorker/serviceWorker.js",
12 | "implicitlyLoadedBefore": [],
13 | "importedBindings": {},
14 | "imports": [],
15 | "isDynamicEntry": false,
16 | "isEntry": true,
17 | "isImplicitEntry": false,
18 | "map": null,
19 | "modules": {
20 | "vite-plugin-web-extension/test/manifest/resources/backgroundServiceWorker/serviceWorker.js": {
21 | "code": "console.log("serviceWorker");",
22 | "originalLength": 30,
23 | "removedExports": [],
24 | "renderedExports": [],
25 | "renderedLength": 29,
26 | },
27 | },
28 | "name": "test/manifest/resources/backgroundServiceWorker/serviceWorker",
29 | "referencedFiles": [],
30 | "type": "chunk",
31 | "viteMetadata": {
32 | "importedAssets": Set {},
33 | "importedCss": Set {},
34 | },
35 | },
36 | {
37 | "fileName": "manifest.json",
38 | "name": undefined,
39 | "source": "{
40 | "version": "1.0.0",
41 | "name": "Manifest Name",
42 | "manifest_version": 3,
43 | "background": {
44 | "service_worker": "serviceWorker.js",
45 | "type": "module"
46 | }
47 | }",
48 | "type": "asset",
49 | },
50 | {
51 | "fileName": "serviceWorker.js",
52 | "name": undefined,
53 | "source": "import "/assets/test/manifest/resources/backgroundServiceWorker/serviceWorker.js";",
54 | "type": "asset",
55 | },
56 | ]
57 | `;
58 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/backgroundServiceWorkerRoot.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`backgroundServiceWorker - Manifest V3 1`] = `
4 | [
5 | {
6 | "code": "console.log("serviceWorker");
7 | ",
8 | "dynamicImports": [],
9 | "exports": [],
10 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/backgroundServiceWorker/serviceWorker.js",
11 | "fileName": "assets/test/manifest/resources/backgroundServiceWorker/serviceWorker.js",
12 | "implicitlyLoadedBefore": [],
13 | "importedBindings": {},
14 | "imports": [],
15 | "isDynamicEntry": false,
16 | "isEntry": true,
17 | "isImplicitEntry": false,
18 | "map": null,
19 | "modules": {
20 | "vite-plugin-web-extension/test/manifest/resources/backgroundServiceWorker/serviceWorker.js": {
21 | "code": "console.log("serviceWorker");",
22 | "originalLength": 30,
23 | "removedExports": [],
24 | "renderedExports": [],
25 | "renderedLength": 29,
26 | },
27 | },
28 | "name": "test/manifest/resources/backgroundServiceWorker/serviceWorker",
29 | "referencedFiles": [],
30 | "type": "chunk",
31 | "viteMetadata": {
32 | "importedAssets": Set {},
33 | "importedCss": Set {},
34 | },
35 | },
36 | {
37 | "fileName": "manifest.json",
38 | "name": undefined,
39 | "source": "{
40 | "version": "1.0.0",
41 | "name": "Manifest Name",
42 | "manifest_version": 3,
43 | "background": {
44 | "service_worker": "serviceWorker.js",
45 | "type": "module"
46 | }
47 | }",
48 | "type": "asset",
49 | },
50 | {
51 | "fileName": "serviceWorker.js",
52 | "name": undefined,
53 | "source": "import "/assets/test/manifest/resources/backgroundServiceWorker/serviceWorker.js";",
54 | "type": "asset",
55 | },
56 | ]
57 | `;
58 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/chromeUrlOverridesHtmlBookmarks.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`chromeUrlOverridesHtmlBookmarks - Manifest V2 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("chromeUrlOverridesHtml");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/bookmarks.html",
14 | "fileName": "assets/test/manifest/resources/chromeUrlOverridesHtml/bookmarks.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/bookmarks.html": {
24 | "code": "",
25 | "originalLength": 241,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 0,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/chromeUrlOverridesHtml.js": {
31 | "code": "log("chromeUrlOverridesHtml");",
32 | "originalLength": 67,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 30,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/chromeUrlOverridesHtml/bookmarks",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 2,
64 | "chrome_url_overrides": {
65 | "bookmarks": "test/manifest/resources/chromeUrlOverridesHtml/bookmarks.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/chromeUrlOverridesHtml/bookmarks.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/chromeUrlOverridesHtmlBookmarks.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`chromeUrlOverridesHtmlBookmarks - Manifest V3 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("chromeUrlOverridesHtml");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/bookmarks.html",
14 | "fileName": "assets/test/manifest/resources/chromeUrlOverridesHtml/bookmarks.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/bookmarks.html": {
24 | "code": "",
25 | "originalLength": 241,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 0,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/chromeUrlOverridesHtml.js": {
31 | "code": "log("chromeUrlOverridesHtml");",
32 | "originalLength": 67,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 30,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/chromeUrlOverridesHtml/bookmarks",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 3,
64 | "chrome_url_overrides": {
65 | "bookmarks": "test/manifest/resources/chromeUrlOverridesHtml/bookmarks.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/chromeUrlOverridesHtml/bookmarks.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/chromeUrlOverridesHtmlHistory.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`chromeUrlOverridesHtmlHistory - Manifest V2 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("chromeUrlOverridesHtml");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/history.html",
14 | "fileName": "assets/test/manifest/resources/chromeUrlOverridesHtml/history.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/chromeUrlOverridesHtml.js": {
24 | "code": "log("chromeUrlOverridesHtml");",
25 | "originalLength": 67,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 30,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/history.html": {
31 | "code": "",
32 | "originalLength": 241,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 0,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/chromeUrlOverridesHtml/history",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 2,
64 | "chrome_url_overrides": {
65 | "history": "test/manifest/resources/chromeUrlOverridesHtml/history.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/chromeUrlOverridesHtml/history.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/chromeUrlOverridesHtmlHistory.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`chromeUrlOverridesHtmlHistory - Manifest V3 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("chromeUrlOverridesHtml");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/history.html",
14 | "fileName": "assets/test/manifest/resources/chromeUrlOverridesHtml/history.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/chromeUrlOverridesHtml.js": {
24 | "code": "log("chromeUrlOverridesHtml");",
25 | "originalLength": 67,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 30,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/history.html": {
31 | "code": "",
32 | "originalLength": 241,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 0,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/chromeUrlOverridesHtml/history",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 3,
64 | "chrome_url_overrides": {
65 | "history": "test/manifest/resources/chromeUrlOverridesHtml/history.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/chromeUrlOverridesHtml/history.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/chromeUrlOverridesHtmlNewTab.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`chromeUrlOverridesHtmlNewTab - Manifest V2 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("chromeUrlOverridesHtml");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/newtab.html",
14 | "fileName": "assets/test/manifest/resources/chromeUrlOverridesHtml/newtab.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/chromeUrlOverridesHtml.js": {
24 | "code": "log("chromeUrlOverridesHtml");",
25 | "originalLength": 67,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 30,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/newtab.html": {
31 | "code": "",
32 | "originalLength": 241,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 0,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/chromeUrlOverridesHtml/newtab",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 2,
64 | "chrome_url_overrides": {
65 | "newtab": "test/manifest/resources/chromeUrlOverridesHtml/newtab.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/chromeUrlOverridesHtml/newtab.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/chromeUrlOverridesHtmlNewTab.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`chromeUrlOverridesHtmlNewTab - Manifest V3 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("chromeUrlOverridesHtml");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/newtab.html",
14 | "fileName": "assets/test/manifest/resources/chromeUrlOverridesHtml/newtab.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/chromeUrlOverridesHtml.js": {
24 | "code": "log("chromeUrlOverridesHtml");",
25 | "originalLength": 67,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 30,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/chromeUrlOverridesHtml/newtab.html": {
31 | "code": "",
32 | "originalLength": 241,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 0,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/chromeUrlOverridesHtml/newtab",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 3,
64 | "chrome_url_overrides": {
65 | "newtab": "test/manifest/resources/chromeUrlOverridesHtml/newtab.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/chromeUrlOverridesHtml/newtab.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/chunkCssRewrite.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`chunkCssRewrite - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "assets/content1.css",
7 | "name": "content1.css",
8 | "source": "#content1 {
9 | display: flex;
10 | }
11 | ",
12 | "type": "asset",
13 | },
14 | {
15 | "fileName": "assets/content2.css",
16 | "name": "content2.css",
17 | "source": "#content2 {
18 | display: flex;
19 | }
20 | ",
21 | "type": "asset",
22 | },
23 | {
24 | "fileName": "assets/contentShared.css",
25 | "name": "contentShared.css",
26 | "source": "#contentShared {
27 | display: flex;
28 | }
29 | ",
30 | "type": "asset",
31 | },
32 | {
33 | "fileName": "manifest.json",
34 | "name": undefined,
35 | "source": "{
36 | "version": "1.0.0",
37 | "name": "Manifest Name",
38 | "manifest_version": 2,
39 | "content_scripts": [
40 | {
41 | "js": [
42 | "test/manifest/resources/chunkCssRewrite/content1.js"
43 | ],
44 | "matches": [
45 | "https://*/*",
46 | "http://*/*"
47 | ]
48 | },
49 | {
50 | "js": [
51 | "test/manifest/resources/chunkCssRewrite/content2.js"
52 | ],
53 | "matches": [
54 | "https://*/*",
55 | "http://*/*"
56 | ]
57 | },
58 | {
59 | "js": [
60 | "test/manifest/resources/chunkCssRewrite/contentNoCss.js"
61 | ],
62 | "matches": [
63 | "https://*/*",
64 | "http://*/*"
65 | ]
66 | }
67 | ],
68 | "web_accessible_resources": [
69 | "assets/content1.css",
70 | "assets/content2.css",
71 | "assets/contentShared.css"
72 | ]
73 | }",
74 | "type": "asset",
75 | },
76 | {
77 | "fileName": "test/manifest/resources/chunkCssRewrite/content1.js",
78 | "name": undefined,
79 | "source": "/* empty css */
80 | console.log(["assets/content1.css","assets/contentShared.css"]);
81 | ",
82 | "type": "asset",
83 | },
84 | {
85 | "fileName": "test/manifest/resources/chunkCssRewrite/content2.js",
86 | "name": undefined,
87 | "source": "/* empty css */
88 | console.log(["assets/content2.css","assets/contentShared.css"]);
89 | ",
90 | "type": "asset",
91 | },
92 | {
93 | "fileName": "test/manifest/resources/chunkCssRewrite/contentNoCss.js",
94 | "name": undefined,
95 | "source": "console.log([]);
96 | ",
97 | "type": "asset",
98 | },
99 | ]
100 | `;
101 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/chunkCssRewrite.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`chunkCssRewrite - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "assets/content1.css",
7 | "name": "content1.css",
8 | "source": "#content1 {
9 | display: flex;
10 | }
11 | ",
12 | "type": "asset",
13 | },
14 | {
15 | "fileName": "assets/content2.css",
16 | "name": "content2.css",
17 | "source": "#content2 {
18 | display: flex;
19 | }
20 | ",
21 | "type": "asset",
22 | },
23 | {
24 | "fileName": "assets/contentShared.css",
25 | "name": "contentShared.css",
26 | "source": "#contentShared {
27 | display: flex;
28 | }
29 | ",
30 | "type": "asset",
31 | },
32 | {
33 | "fileName": "manifest.json",
34 | "name": undefined,
35 | "source": "{
36 | "version": "1.0.0",
37 | "name": "Manifest Name",
38 | "manifest_version": 3,
39 | "content_scripts": [
40 | {
41 | "js": [
42 | "test/manifest/resources/chunkCssRewrite/content1.js"
43 | ],
44 | "matches": [
45 | "https://*/*",
46 | "http://*/*"
47 | ]
48 | },
49 | {
50 | "js": [
51 | "test/manifest/resources/chunkCssRewrite/content2.js"
52 | ],
53 | "matches": [
54 | "https://*/*",
55 | "http://*/*"
56 | ]
57 | },
58 | {
59 | "js": [
60 | "test/manifest/resources/chunkCssRewrite/contentNoCss.js"
61 | ],
62 | "matches": [
63 | "https://*/*",
64 | "http://*/*"
65 | ]
66 | }
67 | ],
68 | "web_accessible_resources": [
69 | {
70 | "resources": [
71 | "assets/content1.css",
72 | "assets/content2.css",
73 | "assets/contentShared.css"
74 | ],
75 | "matches": [
76 | "https://*/*",
77 | "http://*/*"
78 | ]
79 | }
80 | ]
81 | }",
82 | "type": "asset",
83 | },
84 | {
85 | "fileName": "test/manifest/resources/chunkCssRewrite/content1.js",
86 | "name": undefined,
87 | "source": "/* empty css */
88 | console.log(["assets/content1.css","assets/contentShared.css"]);
89 | ",
90 | "type": "asset",
91 | },
92 | {
93 | "fileName": "test/manifest/resources/chunkCssRewrite/content2.js",
94 | "name": undefined,
95 | "source": "/* empty css */
96 | console.log(["assets/content2.css","assets/contentShared.css"]);
97 | ",
98 | "type": "asset",
99 | },
100 | {
101 | "fileName": "test/manifest/resources/chunkCssRewrite/contentNoCss.js",
102 | "name": undefined,
103 | "source": "console.log([]);
104 | ",
105 | "type": "asset",
106 | },
107 | ]
108 | `;
109 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentCss.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentCss - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "assets/test/manifest/resources/contentCss/content1.css",
7 | "name": "test/manifest/resources/contentCss/content1.css",
8 | "source": ".css {
9 | color: red;
10 | }
11 | ",
12 | "type": "asset",
13 | },
14 | {
15 | "fileName": "assets/test/manifest/resources/contentCss/content2.css",
16 | "name": "test/manifest/resources/contentCss/content2.css",
17 | "source": ".css {
18 | color: green;
19 | }",
20 | "type": "asset",
21 | },
22 | {
23 | "fileName": "manifest.json",
24 | "name": undefined,
25 | "source": "{
26 | "version": "1.0.0",
27 | "name": "Manifest Name",
28 | "manifest_version": 2,
29 | "content_scripts": [
30 | {
31 | "js": [
32 | "test/manifest/resources/contentCss/content.js"
33 | ],
34 | "css": [
35 | "assets/test/manifest/resources/contentCss/content1.css",
36 | "assets/test/manifest/resources/contentCss/content2.css"
37 | ],
38 | "matches": [
39 | "https://*/*",
40 | "http://*/*"
41 | ]
42 | }
43 | ]
44 | }",
45 | "type": "asset",
46 | },
47 | {
48 | "fileName": "test/manifest/resources/contentCss/content.js",
49 | "name": undefined,
50 | "source": "console.log("content");
51 | ",
52 | "type": "asset",
53 | },
54 | ]
55 | `;
56 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentCss.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentCss - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "assets/test/manifest/resources/contentCss/content1.css",
7 | "name": "test/manifest/resources/contentCss/content1.css",
8 | "source": ".css {
9 | color: red;
10 | }
11 | ",
12 | "type": "asset",
13 | },
14 | {
15 | "fileName": "assets/test/manifest/resources/contentCss/content2.css",
16 | "name": "test/manifest/resources/contentCss/content2.css",
17 | "source": ".css {
18 | color: green;
19 | }",
20 | "type": "asset",
21 | },
22 | {
23 | "fileName": "manifest.json",
24 | "name": undefined,
25 | "source": "{
26 | "version": "1.0.0",
27 | "name": "Manifest Name",
28 | "manifest_version": 3,
29 | "content_scripts": [
30 | {
31 | "js": [
32 | "test/manifest/resources/contentCss/content.js"
33 | ],
34 | "css": [
35 | "assets/test/manifest/resources/contentCss/content1.css",
36 | "assets/test/manifest/resources/contentCss/content2.css"
37 | ],
38 | "matches": [
39 | "https://*/*",
40 | "http://*/*"
41 | ]
42 | }
43 | ]
44 | }",
45 | "type": "asset",
46 | },
47 | {
48 | "fileName": "test/manifest/resources/contentCss/content.js",
49 | "name": undefined,
50 | "source": "console.log("content");
51 | ",
52 | "type": "asset",
53 | },
54 | ]
55 | `;
56 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentScriptPaths.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentScriptPaths - Manifest V2 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | export {
10 | log as l
11 | };
12 | ",
13 | "dynamicImports": [],
14 | "exports": [
15 | "l",
16 | ],
17 | "facadeModuleId": null,
18 | "fileName": "assets/log.js",
19 | "implicitlyLoadedBefore": [],
20 | "importedBindings": {},
21 | "imports": [],
22 | "isDynamicEntry": false,
23 | "isEntry": false,
24 | "isImplicitEntry": false,
25 | "map": null,
26 | "modules": {
27 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
28 | "code": "function log(message) {
29 | console.log(message);
30 | }",
31 | "originalLength": 65,
32 | "removedExports": [],
33 | "renderedExports": [
34 | "default",
35 | ],
36 | "renderedLength": 49,
37 | },
38 | },
39 | "name": "log",
40 | "referencedFiles": [],
41 | "type": "chunk",
42 | "viteMetadata": {
43 | "importedAssets": Set {},
44 | "importedCss": Set {},
45 | },
46 | },
47 | {
48 | "code": "import { l as log } from "../../../../log.js";
49 | log("content");
50 | ",
51 | "dynamicImports": [],
52 | "exports": [],
53 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/contentWithChunkedImport/content1.js",
54 | "fileName": "assets/test/manifest/resources/contentWithChunkedImport/content1.js",
55 | "implicitlyLoadedBefore": [],
56 | "importedBindings": {
57 | "assets/log.js": [
58 | "l",
59 | ],
60 | },
61 | "imports": [
62 | "assets/log.js",
63 | ],
64 | "isDynamicEntry": false,
65 | "isEntry": true,
66 | "isImplicitEntry": false,
67 | "map": null,
68 | "modules": {
69 | "vite-plugin-web-extension/test/manifest/resources/contentWithChunkedImport/content1.js": {
70 | "code": "log("content");",
71 | "originalLength": 52,
72 | "removedExports": [],
73 | "renderedExports": [],
74 | "renderedLength": 15,
75 | },
76 | },
77 | "name": "test/manifest/resources/contentWithChunkedImport/content1",
78 | "referencedFiles": [],
79 | "type": "chunk",
80 | "viteMetadata": {
81 | "importedAssets": Set {},
82 | "importedCss": Set {},
83 | },
84 | },
85 | {
86 | "code": "import { l as log } from "../../../../log.js";
87 | log("content2");
88 | ",
89 | "dynamicImports": [],
90 | "exports": [],
91 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/contentWithChunkedImport/content2.js",
92 | "fileName": "assets/test/manifest/resources/contentWithChunkedImport/content2.js",
93 | "implicitlyLoadedBefore": [],
94 | "importedBindings": {
95 | "assets/log.js": [
96 | "l",
97 | ],
98 | },
99 | "imports": [
100 | "assets/log.js",
101 | ],
102 | "isDynamicEntry": false,
103 | "isEntry": true,
104 | "isImplicitEntry": false,
105 | "map": null,
106 | "modules": {
107 | "vite-plugin-web-extension/test/manifest/resources/contentWithChunkedImport/content2.js": {
108 | "code": "log("content2");",
109 | "originalLength": 53,
110 | "removedExports": [],
111 | "renderedExports": [],
112 | "renderedLength": 16,
113 | },
114 | },
115 | "name": "test/manifest/resources/contentWithChunkedImport/content2",
116 | "referencedFiles": [],
117 | "type": "chunk",
118 | "viteMetadata": {
119 | "importedAssets": Set {},
120 | "importedCss": Set {},
121 | },
122 | },
123 | {
124 | "fileName": "manifest.json",
125 | "name": undefined,
126 | "source": "{
127 | "version": "1.0.0",
128 | "name": "Manifest Name",
129 | "manifest_version": 2,
130 | "content_scripts": [
131 | {
132 | "js": [
133 | "test/manifest/resources/contentWithChunkedImport/content1.js"
134 | ],
135 | "matches": [
136 | "https://*/*",
137 | "http://*/*"
138 | ]
139 | },
140 | {
141 | "js": [
142 | "test/manifest/resources/contentWithChunkedImport/content2.js"
143 | ],
144 | "matches": [
145 | "https://*/*",
146 | "http://*/*"
147 | ]
148 | }
149 | ],
150 | "web_accessible_resources": [
151 | "assets/log.js",
152 | "assets/test/manifest/resources/contentWithChunkedImport/content1.js",
153 | "assets/test/manifest/resources/contentWithChunkedImport/content2.js"
154 | ]
155 | }",
156 | "type": "asset",
157 | },
158 | {
159 | "fileName": "test/manifest/resources/contentWithChunkedImport/content1.js",
160 | "name": undefined,
161 | "source": "(async()=>{await import(chrome.runtime.getURL("assets/test/manifest/resources/contentWithChunkedImport/content1.js"))})();",
162 | "type": "asset",
163 | },
164 | {
165 | "fileName": "test/manifest/resources/contentWithChunkedImport/content2.js",
166 | "name": undefined,
167 | "source": "(async()=>{await import(chrome.runtime.getURL("assets/test/manifest/resources/contentWithChunkedImport/content2.js"))})();",
168 | "type": "asset",
169 | },
170 | ]
171 | `;
172 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentScriptTypes.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentScriptTypes - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 2,
12 | "content_scripts": [
13 | {
14 | "js": [
15 | "test/manifest/resources/contentScriptTypes/content1.js"
16 | ],
17 | "matches": [
18 | "https://example.com/"
19 | ]
20 | },
21 | {
22 | "js": [
23 | "test/manifest/resources/contentScriptTypes/content2.js"
24 | ],
25 | "matches": [
26 | "https://example.com/"
27 | ]
28 | }
29 | ]
30 | }",
31 | "type": "asset",
32 | },
33 | {
34 | "fileName": "test/manifest/resources/contentScriptTypes/content1.js",
35 | "name": undefined,
36 | "source": "console.log("content1");
37 | ",
38 | "type": "asset",
39 | },
40 | {
41 | "fileName": "test/manifest/resources/contentScriptTypes/content2.js",
42 | "name": undefined,
43 | "source": "console.log("content2");
44 | ",
45 | "type": "asset",
46 | },
47 | ]
48 | `;
49 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentScriptTypes.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentScriptTypes - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 3,
12 | "content_scripts": [
13 | {
14 | "js": [
15 | "test/manifest/resources/contentScriptTypes/content1.js"
16 | ],
17 | "matches": [
18 | "https://example.com/"
19 | ]
20 | },
21 | {
22 | "js": [
23 | "test/manifest/resources/contentScriptTypes/content2.js"
24 | ],
25 | "matches": [
26 | "https://example.com/"
27 | ]
28 | }
29 | ]
30 | }",
31 | "type": "asset",
32 | },
33 | {
34 | "fileName": "test/manifest/resources/contentScriptTypes/content1.js",
35 | "name": undefined,
36 | "source": "console.log("content1");
37 | ",
38 | "type": "asset",
39 | },
40 | {
41 | "fileName": "test/manifest/resources/contentScriptTypes/content2.js",
42 | "name": undefined,
43 | "source": "console.log("content2");
44 | ",
45 | "type": "asset",
46 | },
47 | ]
48 | `;
49 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentWithNoImports.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentWithNoImports - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 2,
12 | "content_scripts": [
13 | {
14 | "js": [
15 | "test/manifest/resources/contentWithNoImports/content.js"
16 | ],
17 | "matches": [
18 | "https://*/*",
19 | "http://*/*"
20 | ]
21 | }
22 | ]
23 | }",
24 | "type": "asset",
25 | },
26 | {
27 | "fileName": "test/manifest/resources/contentWithNoImports/content.js",
28 | "name": undefined,
29 | "source": "console.log("content");
30 | ",
31 | "type": "asset",
32 | },
33 | ]
34 | `;
35 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentWithNoImports.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentWithNoImports - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 3,
12 | "content_scripts": [
13 | {
14 | "js": [
15 | "test/manifest/resources/contentWithNoImports/content.js"
16 | ],
17 | "matches": [
18 | "*://*/*",
19 | "https://*/*",
20 | "*://example.com/",
21 | "https://example.com/",
22 | "*://example.com/subpath/*",
23 | "https://example.com/subpath/*"
24 | ]
25 | }
26 | ]
27 | }",
28 | "type": "asset",
29 | },
30 | {
31 | "fileName": "test/manifest/resources/contentWithNoImports/content.js",
32 | "name": undefined,
33 | "source": "console.log("content");
34 | ",
35 | "type": "asset",
36 | },
37 | ]
38 | `;
39 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentWithSameScriptName.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentWithSameScriptName - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 2,
12 | "content_scripts": [
13 | {
14 | "js": [
15 | "test/manifest/resources/contentWithSameScriptName/content1/content.js"
16 | ],
17 | "matches": [
18 | "https://*/*",
19 | "http://*/*"
20 | ]
21 | },
22 | {
23 | "js": [
24 | "test/manifest/resources/contentWithSameScriptName/content2/content.js"
25 | ],
26 | "matches": [
27 | "https://*/*",
28 | "http://*/*"
29 | ]
30 | }
31 | ]
32 | }",
33 | "type": "asset",
34 | },
35 | {
36 | "fileName": "test/manifest/resources/contentWithSameScriptName/content1/content.js",
37 | "name": undefined,
38 | "source": "console.log("content1");
39 | ",
40 | "type": "asset",
41 | },
42 | {
43 | "fileName": "test/manifest/resources/contentWithSameScriptName/content2/content.js",
44 | "name": undefined,
45 | "source": "console.log("content2");
46 | ",
47 | "type": "asset",
48 | },
49 | ]
50 | `;
51 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentWithSameScriptName.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentWithSameScriptName - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 3,
12 | "content_scripts": [
13 | {
14 | "js": [
15 | "test/manifest/resources/contentWithSameScriptName/content1/content.js"
16 | ],
17 | "matches": [
18 | "*://*/*",
19 | "https://*/*",
20 | "*://example.com/",
21 | "https://example.com/",
22 | "*://example.com/subpath/*",
23 | "https://example.com/subpath/*"
24 | ]
25 | },
26 | {
27 | "js": [
28 | "test/manifest/resources/contentWithSameScriptName/content2/content.js"
29 | ],
30 | "matches": [
31 | "*://*/*",
32 | "https://*/*",
33 | "*://example.com/",
34 | "https://example.com/",
35 | "*://example.com/subpath/*",
36 | "https://example.com/subpath/*"
37 | ]
38 | }
39 | ]
40 | }",
41 | "type": "asset",
42 | },
43 | {
44 | "fileName": "test/manifest/resources/contentWithSameScriptName/content1/content.js",
45 | "name": undefined,
46 | "source": "console.log("content1");
47 | ",
48 | "type": "asset",
49 | },
50 | {
51 | "fileName": "test/manifest/resources/contentWithSameScriptName/content2/content.js",
52 | "name": undefined,
53 | "source": "console.log("content2");
54 | ",
55 | "type": "asset",
56 | },
57 | ]
58 | `;
59 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentWithUnchunkedImport.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentWithUnchunkedImport - Manifest V2 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 2,
12 | "content_scripts": [
13 | {
14 | "js": [
15 | "test/manifest/resources/contentWithUnchunkedImport/content.js"
16 | ],
17 | "matches": [
18 | "https://*/*",
19 | "http://*/*"
20 | ]
21 | }
22 | ]
23 | }",
24 | "type": "asset",
25 | },
26 | {
27 | "fileName": "test/manifest/resources/contentWithUnchunkedImport/content.js",
28 | "name": undefined,
29 | "source": "function log(message) {
30 | console.log(message);
31 | }
32 | log("content");
33 | ",
34 | "type": "asset",
35 | },
36 | ]
37 | `;
38 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/contentWithUnchunkedImport.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`contentWithUnchunkedImport - Manifest V3 1`] = `
4 | [
5 | {
6 | "fileName": "manifest.json",
7 | "name": undefined,
8 | "source": "{
9 | "version": "1.0.0",
10 | "name": "Manifest Name",
11 | "manifest_version": 3,
12 | "content_scripts": [
13 | {
14 | "js": [
15 | "test/manifest/resources/contentWithUnchunkedImport/content.js"
16 | ],
17 | "matches": [
18 | "*://*/*",
19 | "https://*/*",
20 | "*://example.com/",
21 | "https://example.com/",
22 | "*://example.com/subpath/*",
23 | "https://example.com/subpath/*"
24 | ]
25 | }
26 | ]
27 | }",
28 | "type": "asset",
29 | },
30 | {
31 | "fileName": "test/manifest/resources/contentWithUnchunkedImport/content.js",
32 | "name": undefined,
33 | "source": "function log(message) {
34 | console.log(message);
35 | }
36 | log("content");
37 | ",
38 | "type": "asset",
39 | },
40 | ]
41 | `;
42 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/devtoolsHtml.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`devtoolsHtml - Manifest V2 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("devtools");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/devtoolsHtml/devtools.html",
14 | "fileName": "assets/test/manifest/resources/devtoolsHtml/devtools.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/devtoolsHtml/devtools.html": {
24 | "code": "",
25 | "originalLength": 227,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 0,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/devtoolsHtml/devtools.js": {
31 | "code": "log("devtools");",
32 | "originalLength": 53,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 16,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/devtoolsHtml/devtools",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 2,
64 | "devtools_page": "test/manifest/resources/devtoolsHtml/devtools.html"
65 | }",
66 | "type": "asset",
67 | },
68 | {
69 | "fileName": "test/manifest/resources/devtoolsHtml/devtools.html",
70 | "name": undefined,
71 | "source": "
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | ",
81 | "type": "asset",
82 | },
83 | ]
84 | `;
85 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/devtoolsHtml.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`devtoolsHtml - Manifest V3 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("devtools");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/devtoolsHtml/devtools.html",
14 | "fileName": "assets/test/manifest/resources/devtoolsHtml/devtools.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/devtoolsHtml/devtools.html": {
24 | "code": "",
25 | "originalLength": 227,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 0,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/devtoolsHtml/devtools.js": {
31 | "code": "log("devtools");",
32 | "originalLength": 53,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 16,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/devtoolsHtml/devtools",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 3,
64 | "devtools_page": "test/manifest/resources/devtoolsHtml/devtools.html"
65 | }",
66 | "type": "asset",
67 | },
68 | {
69 | "fileName": "test/manifest/resources/devtoolsHtml/devtools.html",
70 | "name": undefined,
71 | "source": "
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | ",
81 | "type": "asset",
82 | },
83 | ]
84 | `;
85 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/optionsHtml.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`optionsHtml - Manifest V2 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("options");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/optionsHtml/options.html",
14 | "fileName": "assets/test/manifest/resources/optionsHtml/options.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/optionsHtml/options.html": {
24 | "code": "",
25 | "originalLength": 226,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 0,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/optionsHtml/options.js": {
31 | "code": "log("options");",
32 | "originalLength": 52,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 15,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/optionsHtml/options",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 2,
64 | "options_ui": {
65 | "page": "test/manifest/resources/optionsHtml/options.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/optionsHtml/options.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/optionsHtml.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`optionsHtml - Manifest V3 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("options");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/optionsHtml/options.html",
14 | "fileName": "assets/test/manifest/resources/optionsHtml/options.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/optionsHtml/options.html": {
24 | "code": "",
25 | "originalLength": 226,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 0,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/optionsHtml/options.js": {
31 | "code": "log("options");",
32 | "originalLength": 52,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 15,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/optionsHtml/options",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 3,
64 | "options_ui": {
65 | "page": "test/manifest/resources/optionsHtml/options.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/optionsHtml/options.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/popupHtml.v2.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`popupHtml - Manifest V2 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("popup");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/popupHtml/popup.html",
14 | "fileName": "assets/test/manifest/resources/popupHtml/popup.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/popupHtml/popup.html": {
24 | "code": "",
25 | "originalLength": 224,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 0,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/popupHtml/popup.js": {
31 | "code": "log("popup");",
32 | "originalLength": 50,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 13,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/popupHtml/popup",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 2,
64 | "browser_action": {
65 | "default_popup": "test/manifest/resources/popupHtml/popup.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/popupHtml/popup.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/popupHtml.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`popupHtml - Manifest V3 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("popup");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/popupHtml/popup.html",
14 | "fileName": "assets/test/manifest/resources/popupHtml/popup.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/popupHtml/popup.html": {
24 | "code": "",
25 | "originalLength": 224,
26 | "removedExports": [],
27 | "renderedExports": [],
28 | "renderedLength": 0,
29 | },
30 | "vite-plugin-web-extension/test/manifest/resources/popupHtml/popup.js": {
31 | "code": "log("popup");",
32 | "originalLength": 50,
33 | "removedExports": [],
34 | "renderedExports": [],
35 | "renderedLength": 13,
36 | },
37 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
38 | "code": "function log(message) {
39 | console.log(message);
40 | }",
41 | "originalLength": 65,
42 | "removedExports": [],
43 | "renderedExports": [
44 | "default",
45 | ],
46 | "renderedLength": 49,
47 | },
48 | },
49 | "name": "test/manifest/resources/popupHtml/popup",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 3,
64 | "action": {
65 | "default_popup": "test/manifest/resources/popupHtml/popup.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/popupHtml/popup.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/__snapshots__/sidePanelHtml.v3.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`sidePanelHtml - Manifest V3 1`] = `
4 | [
5 | {
6 | "code": "function log(message) {
7 | console.log(message);
8 | }
9 | log("sidepanel");
10 | ",
11 | "dynamicImports": [],
12 | "exports": [],
13 | "facadeModuleId": "vite-plugin-web-extension/test/manifest/resources/sidePanelHtml/sidepanel.html",
14 | "fileName": "assets/test/manifest/resources/sidePanelHtml/sidepanel.js",
15 | "implicitlyLoadedBefore": [],
16 | "importedBindings": {},
17 | "imports": [],
18 | "isDynamicEntry": false,
19 | "isEntry": true,
20 | "isImplicitEntry": false,
21 | "map": null,
22 | "modules": {
23 | "vite-plugin-web-extension/test/manifest/resources/shared/log.js": {
24 | "code": "function log(message) {
25 | console.log(message);
26 | }",
27 | "originalLength": 65,
28 | "removedExports": [],
29 | "renderedExports": [
30 | "default",
31 | ],
32 | "renderedLength": 49,
33 | },
34 | "vite-plugin-web-extension/test/manifest/resources/sidePanelHtml/sidepanel.html": {
35 | "code": "",
36 | "originalLength": 228,
37 | "removedExports": [],
38 | "renderedExports": [],
39 | "renderedLength": 0,
40 | },
41 | "vite-plugin-web-extension/test/manifest/resources/sidePanelHtml/sidepanel.js": {
42 | "code": "log("sidepanel");",
43 | "originalLength": 54,
44 | "removedExports": [],
45 | "renderedExports": [],
46 | "renderedLength": 17,
47 | },
48 | },
49 | "name": "test/manifest/resources/sidePanelHtml/sidepanel",
50 | "referencedFiles": [],
51 | "type": "chunk",
52 | "viteMetadata": {
53 | "importedAssets": Set {},
54 | "importedCss": Set {},
55 | },
56 | },
57 | {
58 | "fileName": "manifest.json",
59 | "name": undefined,
60 | "source": "{
61 | "version": "1.0.0",
62 | "name": "Manifest Name",
63 | "manifest_version": 3,
64 | "side_panel": {
65 | "default_path": "test/manifest/resources/sidePanelHtml/sidepanel.html"
66 | }
67 | }",
68 | "type": "asset",
69 | },
70 | {
71 | "fileName": "test/manifest/resources/sidePanelHtml/sidepanel.html",
72 | "name": undefined,
73 | "source": "
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ",
83 | "type": "asset",
84 | },
85 | ]
86 | `;
87 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsHtml.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsHtml");
4 |
5 | runManifestV2Test("additionalInputsHtml", () => ({}), {
6 | additionalInputs: {
7 | html: [`${resourceDir}/html.html`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsHtml.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsHtml");
4 |
5 | runManifestV3Test("additionalInputsHtml", () => ({}), {
6 | additionalInputs: {
7 | html: [`${resourceDir}/html.html`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsScriptsChunkedImport.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsScriptsChunkedImport");
4 |
5 | runManifestV2Test("additionalInputsScriptsChunkedImport", () => ({}), {
6 | additionalInputs: {
7 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsScriptsChunkedImport.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsScriptsChunkedImport");
4 |
5 | runManifestV3Test("additionalInputsScriptsChunkedImport", () => ({}), {
6 | additionalInputs: {
7 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsScriptsNoImport.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsScriptsNoImport");
4 |
5 | runManifestV2Test("additionalInputsScriptsNoImport", () => ({}), {
6 | additionalInputs: {
7 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsScriptsNoImport.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsScriptsNoImport");
4 |
5 | runManifestV3Test("additionalInputsScriptsNoImport", () => ({}), {
6 | additionalInputs: {
7 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsScriptsTypes.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsScriptsTypes");
4 |
5 | runManifestV2Test("additionalInputsScriptsTypes", () => ({}), {
6 | additionalInputs: {
7 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.ts`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsScriptsTypes.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsScriptsTypes");
4 |
5 | runManifestV3Test("additionalInputsScriptsTypes", () => ({}), {
6 | additionalInputs: {
7 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.ts`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsScriptsUnchunkedImport.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsScriptsUnchunkedImport");
4 |
5 | runManifestV2Test("additionalInputsScriptsUnchunkedImport", () => ({}), {
6 | additionalInputs: {
7 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsScriptsUnchunkedImport.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsScriptsUnchunkedImport");
4 |
5 | runManifestV3Test("additionalInputsScriptsUnchunkedImport", () => ({}), {
6 | additionalInputs: {
7 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsStylesTypes.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsStylesTypes");
4 |
5 | runManifestV2Test("additionalInputsStylesTypes", () => ({}), {
6 | additionalInputs: {
7 | styles: [`${resourceDir}/style1.css`, `${resourceDir}/style2.scss`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsStylesTypes.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsStylesTypes");
4 |
5 | runManifestV3Test("additionalInputsStylesTypes", () => ({}), {
6 | additionalInputs: {
7 | styles: [`${resourceDir}/style1.css`, `${resourceDir}/style2.scss`],
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsWebAccessible.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsWebAccessible");
4 |
5 | runManifestV2Test("additionalInputsWebAccessible", () => ({}), {
6 | additionalInputs: {
7 | scripts: [
8 | `${resourceDir}/script1.js`,
9 | {
10 | fileName: `${resourceDir}/script2.js`,
11 | webAccessible: false,
12 | },
13 | {
14 | fileName: `${resourceDir}/script3.js`,
15 | webAccessible: true,
16 | },
17 | {
18 | fileName: `${resourceDir}/script4.js`,
19 | webAccessible: {
20 | matches: ["https://example.com/"],
21 | },
22 | },
23 | {
24 | fileName: `${resourceDir}/script5.ts`,
25 | webAccessible: {
26 | extensionIds: ["oilkjaldkfjlasdf"],
27 | },
28 | },
29 | {
30 | fileName: `${resourceDir}/chunkedScript1.js`,
31 | webAccessible: {
32 | matches: ["https://example.com/"],
33 | },
34 | },
35 | {
36 | fileName: `${resourceDir}/chunkedScript2.js`,
37 | webAccessible: {
38 | matches: ["https://example.com/"],
39 | },
40 | },
41 | {
42 | fileName: `${resourceDir}/chunkedScript3.js`,
43 | webAccessible: {
44 | extensionIds: ["oilkjaldkfjlasdf"],
45 | },
46 | },
47 | ],
48 | },
49 | });
50 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsWebAccessible.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsWebAccessible");
4 |
5 | runManifestV3Test("additionalInputsWebAccessible", () => ({}), {
6 | additionalInputs: {
7 | scripts: [
8 | `${resourceDir}/script1.js`,
9 | {
10 | fileName: `${resourceDir}/script2.js`,
11 | webAccessible: false,
12 | },
13 | {
14 | fileName: `${resourceDir}/script3.js`,
15 | webAccessible: true,
16 | },
17 | {
18 | fileName: `${resourceDir}/script4.js`,
19 | webAccessible: {
20 | matches: ["https://example.com/"],
21 | },
22 | },
23 | {
24 | fileName: `${resourceDir}/script5.ts`,
25 | webAccessible: {
26 | extensionIds: ["oilkjaldkfjlasdf"],
27 | },
28 | },
29 | {
30 | fileName: `${resourceDir}/chunkedScript1.js`,
31 | webAccessible: {
32 | matches: ["https://example.com/"],
33 | },
34 | },
35 | {
36 | fileName: `${resourceDir}/chunkedScript2.js`,
37 | webAccessible: {
38 | matches: ["https://example.com/"],
39 | },
40 | },
41 | {
42 | fileName: `${resourceDir}/chunkedScript3.js`,
43 | webAccessible: {
44 | extensionIds: ["oilkjaldkfjlasdf"],
45 | },
46 | },
47 | ],
48 | },
49 | });
50 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsWebAccessibleExcludeEntryFile.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsWebAccessible");
4 |
5 | runManifestV2Test("additionalInputsWebAccessible", () => ({}), {
6 | additionalInputs: {
7 | scripts: [
8 | `${resourceDir}/script1.js`,
9 | {
10 | fileName: `${resourceDir}/script2.js`,
11 | webAccessible: {
12 | matches: ["https://example.com/"],
13 | },
14 | },
15 | {
16 | fileName: `${resourceDir}/script3.js`,
17 | webAccessible: {
18 | matches: ["https://example.com/"],
19 | excludeEntryFile: false,
20 | },
21 | },
22 | {
23 | fileName: `${resourceDir}/script4.js`,
24 | webAccessible: {
25 | matches: ["https://example.com/"],
26 | excludeEntryFile: true,
27 | },
28 | },
29 | {
30 | fileName: `${resourceDir}/script5.ts`,
31 | webAccessible: {
32 | extensionIds: ["oilkjaldkfjlasdf"],
33 | },
34 | },
35 | {
36 | fileName: `${resourceDir}/script6.js`,
37 | webAccessible: {
38 | extensionIds: ["oilkjaldkfjlasdf"],
39 | excludeEntryFile: false,
40 | },
41 | },
42 | {
43 | fileName: `${resourceDir}/script7.js`,
44 | webAccessible: {
45 | extensionIds: ["oilkjaldkfjlasdf"],
46 | excludeEntryFile: true,
47 | },
48 | },
49 | {
50 | fileName: `${resourceDir}/chunkedScript1.js`,
51 | webAccessible: {
52 | matches: ["https://example.com/"],
53 | },
54 | },
55 | {
56 | fileName: `${resourceDir}/chunkedScript2.js`,
57 | webAccessible: {
58 | matches: ["https://example.com/"],
59 | excludeEntryFile: false,
60 | },
61 | },
62 | {
63 | fileName: `${resourceDir}/chunkedScript3.js`,
64 | webAccessible: {
65 | matches: ["https://example.com/"],
66 | excludeEntryFile: true,
67 | },
68 | },
69 | ],
70 | },
71 | });
72 |
--------------------------------------------------------------------------------
/test/manifest/additionalInputsWebAccessibleExcludeEntryFile.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("additionalInputsWebAccessible");
4 |
5 | runManifestV3Test("additionalInputsWebAccessible", () => ({}), {
6 | additionalInputs: {
7 | scripts: [
8 | `${resourceDir}/script1.js`,
9 | {
10 | fileName: `${resourceDir}/script2.js`,
11 | webAccessible: {
12 | matches: ["https://example.com/"],
13 | },
14 | },
15 | {
16 | fileName: `${resourceDir}/script3.js`,
17 | webAccessible: {
18 | matches: ["https://example.com/"],
19 | excludeEntryFile: false,
20 | },
21 | },
22 | {
23 | fileName: `${resourceDir}/script4.js`,
24 | webAccessible: {
25 | matches: ["https://example.com/"],
26 | excludeEntryFile: true,
27 | },
28 | },
29 | {
30 | fileName: `${resourceDir}/script5.ts`,
31 | webAccessible: {
32 | extensionIds: ["oilkjaldkfjlasdf"],
33 | },
34 | },
35 | {
36 | fileName: `${resourceDir}/script6.js`,
37 | webAccessible: {
38 | extensionIds: ["oilkjaldkfjlasdf"],
39 | excludeEntryFile: false,
40 | },
41 | },
42 | {
43 | fileName: `${resourceDir}/script7.js`,
44 | webAccessible: {
45 | extensionIds: ["oilkjaldkfjlasdf"],
46 | excludeEntryFile: true,
47 | },
48 | },
49 | {
50 | fileName: `${resourceDir}/chunkedScript1.js`,
51 | webAccessible: {
52 | matches: ["https://example.com/"],
53 | },
54 | },
55 | {
56 | fileName: `${resourceDir}/chunkedScript2.js`,
57 | webAccessible: {
58 | matches: ["https://example.com/"],
59 | excludeEntryFile: false,
60 | },
61 | },
62 | {
63 | fileName: `${resourceDir}/chunkedScript3.js`,
64 | webAccessible: {
65 | matches: ["https://example.com/"],
66 | excludeEntryFile: true,
67 | },
68 | },
69 | ],
70 | },
71 | });
72 |
--------------------------------------------------------------------------------
/test/manifest/backgroundHtml.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("backgroundHtml");
4 |
5 | runManifestV2Test("backgroundHtml", () => ({
6 | background: {
7 | page: `${resourceDir}/background.html`,
8 | persistent: false,
9 | },
10 | }));
11 |
--------------------------------------------------------------------------------
/test/manifest/backgroundScript.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("backgroundScript");
4 |
5 | runManifestV2Test("backgroundScript", () => ({
6 | background: {
7 | scripts: [`/${resourceDir}/background.js`],
8 | persistent: false,
9 | },
10 | }));
11 |
--------------------------------------------------------------------------------
/test/manifest/backgroundServiceWorker.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("backgroundServiceWorker");
4 |
5 | runManifestV3Test("backgroundServiceWorker", () => ({
6 | background: {
7 | service_worker: `${resourceDir}/serviceWorker.js`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/backgroundServiceWorkerRelative.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("backgroundServiceWorker");
4 | const resourceDirRelative = `./${resourceDir}`;
5 |
6 | runManifestV3Test("backgroundServiceWorker", () => ({
7 | background: {
8 | service_worker: `${resourceDirRelative}/serviceWorker.js`,
9 | },
10 | }));
11 |
--------------------------------------------------------------------------------
/test/manifest/backgroundServiceWorkerRoot.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("backgroundServiceWorker");
4 | const resourceDirRoot = `/${resourceDir}`;
5 |
6 | runManifestV3Test("backgroundServiceWorker", () => ({
7 | background: {
8 | service_worker: `${resourceDirRoot}/serviceWorker.js`,
9 | },
10 | }));
11 |
--------------------------------------------------------------------------------
/test/manifest/chromeUrlOverridesHtmlBookmarks.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("chromeUrlOverridesHtml");
4 |
5 | runManifestV2Test("chromeUrlOverridesHtmlBookmarks", () => ({
6 | chrome_url_overrides: {
7 | bookmarks: `${resourceDir}/bookmarks.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/chromeUrlOverridesHtmlBookmarks.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("chromeUrlOverridesHtml");
4 |
5 | runManifestV3Test("chromeUrlOverridesHtmlBookmarks", () => ({
6 | chrome_url_overrides: {
7 | bookmarks: `${resourceDir}/bookmarks.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/chromeUrlOverridesHtmlHistory.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("chromeUrlOverridesHtml");
4 |
5 | runManifestV2Test("chromeUrlOverridesHtmlHistory", () => ({
6 | chrome_url_overrides: {
7 | history: `${resourceDir}/history.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/chromeUrlOverridesHtmlHistory.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("chromeUrlOverridesHtml");
4 |
5 | runManifestV3Test("chromeUrlOverridesHtmlHistory", () => ({
6 | chrome_url_overrides: {
7 | history: `${resourceDir}/history.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/chromeUrlOverridesHtmlNewTab.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("chromeUrlOverridesHtml");
4 |
5 | runManifestV2Test("chromeUrlOverridesHtmlNewTab", () => ({
6 | chrome_url_overrides: {
7 | newtab: `${resourceDir}/newtab.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/chromeUrlOverridesHtmlNewTab.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("chromeUrlOverridesHtml");
4 |
5 | runManifestV3Test("chromeUrlOverridesHtmlNewTab", () => ({
6 | chrome_url_overrides: {
7 | newtab: `${resourceDir}/newtab.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/chunkCssRewrite.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("chunkCssRewrite");
4 |
5 | runManifestV2Test("chunkCssRewrite", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content1.js`],
9 | matches: ["https://*/*", "http://*/*"],
10 | },
11 | {
12 | js: [`${resourceDir}/content2.js`],
13 | matches: ["https://*/*", "http://*/*"],
14 | },
15 | {
16 | js: [`${resourceDir}/contentNoCss.js`],
17 | matches: ["https://*/*", "http://*/*"],
18 | },
19 | ],
20 | }));
21 |
--------------------------------------------------------------------------------
/test/manifest/chunkCssRewrite.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("chunkCssRewrite");
4 |
5 | runManifestV3Test("chunkCssRewrite", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content1.js`],
9 | matches: ["https://*/*", "http://*/*"],
10 | },
11 | {
12 | js: [`${resourceDir}/content2.js`],
13 | matches: ["https://*/*", "http://*/*"],
14 | },
15 | {
16 | js: [`${resourceDir}/contentNoCss.js`],
17 | matches: ["https://*/*", "http://*/*"],
18 | },
19 | ],
20 | }));
21 |
--------------------------------------------------------------------------------
/test/manifest/contentCss.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentCss");
4 |
5 | runManifestV2Test("contentCss", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content.js`],
9 | css: [`${resourceDir}/content1.css`, `${resourceDir}/content2.scss`],
10 | matches: ["https://*/*", "http://*/*"],
11 | },
12 | ],
13 | }));
14 |
--------------------------------------------------------------------------------
/test/manifest/contentCss.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentCss");
4 |
5 | runManifestV3Test("contentCss", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content.js`],
9 | css: [`${resourceDir}/content1.css`, `${resourceDir}/content2.scss`],
10 | matches: ["https://*/*", "http://*/*"],
11 | },
12 | ],
13 | }));
14 |
--------------------------------------------------------------------------------
/test/manifest/contentScriptPaths.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithChunkedImport");
4 | const resourceDirRoot = `/${resourceDir}`;
5 | const resourceDirRelative = `./${resourceDir}`;
6 |
7 | runManifestV2Test("contentScriptPaths", () => ({
8 | content_scripts: [
9 | {
10 | js: [`${resourceDirRoot}/content1.js`],
11 | matches: ["https://*/*", "http://*/*"],
12 | },
13 | {
14 | js: [`${resourceDirRelative}/content2.js`],
15 | matches: ["https://*/*", "http://*/*"],
16 | },
17 | ],
18 | }));
19 |
--------------------------------------------------------------------------------
/test/manifest/contentScriptPaths.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithChunkedImport");
4 | const resourceDirRoot = `/${resourceDir}`;
5 | const resourceDirRelative = `./${resourceDir}`;
6 |
7 | runManifestV3Test("contentScriptPaths", () => ({
8 | content_scripts: [
9 | {
10 | js: [`${resourceDirRoot}/content1.js`],
11 | matches: ["https://*/*", "http://*/*"],
12 | },
13 | {
14 | js: [`${resourceDirRelative}/content2.js`],
15 | matches: ["https://*/*", "http://*/*"],
16 | },
17 | ],
18 | }));
19 |
--------------------------------------------------------------------------------
/test/manifest/contentScriptTypes.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentScriptTypes");
4 |
5 | runManifestV2Test("contentScriptTypes", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content1.js`],
9 | matches: ["https://example.com/"],
10 | },
11 | {
12 | js: [`${resourceDir}/content2.ts`],
13 | matches: ["https://example.com/"],
14 | },
15 | ],
16 | }));
17 |
--------------------------------------------------------------------------------
/test/manifest/contentScriptTypes.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentScriptTypes");
4 |
5 | runManifestV3Test("contentScriptTypes", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content1.js`],
9 | matches: ["https://example.com/"],
10 | },
11 | {
12 | js: [`${resourceDir}/content2.ts`],
13 | matches: ["https://example.com/"],
14 | },
15 | ],
16 | }));
17 |
--------------------------------------------------------------------------------
/test/manifest/contentWithChunkedImport.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithChunkedImport");
4 |
5 | runManifestV2Test("contentWithChunkedImport", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content1.js`],
9 | matches: ["https://*/*", "http://*/*"],
10 | },
11 | {
12 | js: [`${resourceDir}/content2.js`],
13 | matches: ["https://*/*", "http://*/*"],
14 | },
15 | ],
16 | }));
17 |
--------------------------------------------------------------------------------
/test/manifest/contentWithChunkedImport.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithChunkedImport");
4 |
5 | runManifestV3Test("contentWithChunkedImport", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content1.js`],
9 | matches: [
10 | "*://*/*",
11 | "https://*/*",
12 | "*://example.com/",
13 | "https://example.com/",
14 | "*://example.com/subpath/*",
15 | "https://example.com/subpath/*",
16 | ],
17 | },
18 | {
19 | js: [`${resourceDir}/content2.js`],
20 | matches: [
21 | "*://*/*",
22 | "https://*/*",
23 | "*://example.com/",
24 | "https://example.com/",
25 | "*://example.com/subpath/*",
26 | "https://example.com/subpath/*",
27 | ],
28 | },
29 | ],
30 | }));
31 |
--------------------------------------------------------------------------------
/test/manifest/contentWithDynamicImport.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithDynamicImport");
4 |
5 | runManifestV2Test("contentWithDynamicImport", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content1.js`],
9 | matches: ["https://*/*", "http://*/*"],
10 | },
11 | {
12 | js: [`${resourceDir}/content2.js`],
13 | matches: ["https://*/*", "http://*/*"],
14 | },
15 | ],
16 | }));
17 |
--------------------------------------------------------------------------------
/test/manifest/contentWithDynamicImport.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithDynamicImport");
4 |
5 | runManifestV3Test("contentWithDynamicImport", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content1.js`],
9 | matches: [
10 | "*://*/*",
11 | "https://*/*",
12 | "*://example.com/",
13 | "https://example.com/",
14 | "*://example.com/subpath/*",
15 | "https://example.com/subpath/*",
16 | ],
17 | },
18 | {
19 | js: [`${resourceDir}/content2.js`],
20 | matches: [
21 | "*://*/*",
22 | "https://*/*",
23 | "*://example.com/",
24 | "https://example.com/",
25 | "*://example.com/subpath/*",
26 | "https://example.com/subpath/*",
27 | ],
28 | },
29 | ],
30 | }));
31 |
--------------------------------------------------------------------------------
/test/manifest/contentWithNoImports.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithNoImports");
4 |
5 | runManifestV2Test("contentWithNoImports", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content.js`],
9 | matches: ["https://*/*", "http://*/*"],
10 | },
11 | ],
12 | }));
13 |
--------------------------------------------------------------------------------
/test/manifest/contentWithNoImports.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithNoImports");
4 |
5 | runManifestV3Test("contentWithNoImports", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content.js`],
9 | matches: [
10 | "*://*/*",
11 | "https://*/*",
12 | "*://example.com/",
13 | "https://example.com/",
14 | "*://example.com/subpath/*",
15 | "https://example.com/subpath/*",
16 | ],
17 | },
18 | ],
19 | }));
20 |
--------------------------------------------------------------------------------
/test/manifest/contentWithSameScriptName.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithSameScriptName");
4 |
5 | runManifestV2Test("contentWithSameScriptName", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content1/content.js`],
9 | matches: ["https://*/*", "http://*/*"],
10 | },
11 | {
12 | js: [`${resourceDir}/content2/content.js`],
13 | matches: ["https://*/*", "http://*/*"],
14 | },
15 | ],
16 | }));
17 |
--------------------------------------------------------------------------------
/test/manifest/contentWithSameScriptName.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithSameScriptName");
4 |
5 | runManifestV3Test("contentWithSameScriptName", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content1/content.js`],
9 | matches: [
10 | "*://*/*",
11 | "https://*/*",
12 | "*://example.com/",
13 | "https://example.com/",
14 | "*://example.com/subpath/*",
15 | "https://example.com/subpath/*",
16 | ],
17 | },
18 | {
19 | js: [`${resourceDir}/content2/content.js`],
20 | matches: [
21 | "*://*/*",
22 | "https://*/*",
23 | "*://example.com/",
24 | "https://example.com/",
25 | "*://example.com/subpath/*",
26 | "https://example.com/subpath/*",
27 | ],
28 | },
29 | ],
30 | }));
31 |
--------------------------------------------------------------------------------
/test/manifest/contentWithUnchunkedImport.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithUnchunkedImport");
4 |
5 | runManifestV2Test("contentWithUnchunkedImport", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content.js`],
9 | matches: ["https://*/*", "http://*/*"],
10 | },
11 | ],
12 | }));
13 |
--------------------------------------------------------------------------------
/test/manifest/contentWithUnchunkedImport.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("contentWithUnchunkedImport");
4 |
5 | runManifestV3Test("contentWithUnchunkedImport", () => ({
6 | content_scripts: [
7 | {
8 | js: [`${resourceDir}/content.js`],
9 | matches: [
10 | "*://*/*",
11 | "https://*/*",
12 | "*://example.com/",
13 | "https://example.com/",
14 | "*://example.com/subpath/*",
15 | "https://example.com/subpath/*",
16 | ],
17 | },
18 | ],
19 | }));
20 |
--------------------------------------------------------------------------------
/test/manifest/devtoolsHtml.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("devtoolsHtml");
4 |
5 | runManifestV2Test("devtoolsHtml", () => ({
6 | devtools_page: `${resourceDir}/devtools.html`,
7 | }));
8 |
--------------------------------------------------------------------------------
/test/manifest/devtoolsHtml.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("devtoolsHtml");
4 |
5 | runManifestV3Test("devtoolsHtml", () => ({
6 | devtools_page: `${resourceDir}/devtools.html`,
7 | }));
8 |
--------------------------------------------------------------------------------
/test/manifest/fullExtension.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("fullExtension");
4 |
5 | runManifestV2Test(
6 | "fullExtension",
7 | () => ({
8 | background: {
9 | scripts: [`${resourceDir}/src/entries/background/main.js`],
10 | persistent: false,
11 | },
12 | content_scripts: [
13 | {
14 | js: [`${resourceDir}/src/entries/contentScript/primary/main.js`],
15 | matches: ["*://*/*"],
16 | },
17 | ],
18 | browser_action: {
19 | default_icon: {
20 | 32: `${resourceDir}/src/assets/logo.svg`,
21 | },
22 | // default_popup: `${resourceDir}/src/entries/popup/index.html`,
23 | },
24 | options_ui: {
25 | chrome_style: false,
26 | open_in_tab: true,
27 | page: `${resourceDir}/src/entries/options/index.html`,
28 | },
29 | permissions: ["*://*/*"],
30 | }),
31 | {
32 | additionalInputs: {
33 | scripts: [`${resourceDir}/src/lib.js`],
34 | },
35 | }
36 | );
37 |
--------------------------------------------------------------------------------
/test/manifest/fullExtension.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("fullExtension");
4 |
5 | runManifestV3Test(
6 | "fullExtension",
7 | () => ({
8 | action: {
9 | default_icon: {
10 | 32: `${resourceDir}/src/assets/logo.svg`,
11 | },
12 | // default_popup: `${resourceDir}/src/entries/popup/index.html`,
13 | },
14 | background: {
15 | service_worker: `${resourceDir}/src/entries/background/main.js`,
16 | },
17 | content_scripts: [
18 | {
19 | js: [`${resourceDir}/src/entries/contentScript/primary/main.js`],
20 | matches: ["*://*/*"],
21 | },
22 | ],
23 | host_permissions: ["*://*/*"],
24 | permissions: ["scripting", "tabs"],
25 | icons: {
26 | 512: `${resourceDir}/src/assets/logo.svg`,
27 | },
28 | options_ui: {
29 | page: `${resourceDir}/src/entries/options/index.html`,
30 | open_in_tab: true,
31 | },
32 | }),
33 | {
34 | additionalInputs: {
35 | scripts: [`${resourceDir}/src/lib.js`],
36 | },
37 | }
38 | );
39 |
--------------------------------------------------------------------------------
/test/manifest/htmlUrlProperties.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("htmlUrlProperties");
4 |
5 | runManifestV2Test("htmlUrlProperties", () => ({
6 | browser_action: {
7 | default_popup: `${resourceDir}/popup.html#hashValue`,
8 | },
9 | devtools_page: `${resourceDir}/devtools.html?query=1`,
10 | options_ui: {
11 | page: `${resourceDir}/options.html?query=1#hashValue`,
12 | },
13 | }));
14 |
--------------------------------------------------------------------------------
/test/manifest/htmlUrlProperties.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("htmlUrlProperties");
4 |
5 | runManifestV3Test("htmlUrlProperties", () => ({
6 | action: {
7 | default_popup: `${resourceDir}/popup.html#hashValue`,
8 | },
9 | devtools_page: `${resourceDir}/devtools.html?query=1`,
10 | options_ui: {
11 | page: `${resourceDir}/options.html?query=1#hashValue`,
12 | },
13 | }));
14 |
--------------------------------------------------------------------------------
/test/manifest/manifestTestUtils.ts:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 | import type { RollupOutput } from "rollup";
3 | import { build, normalizePath } from "vite";
4 | import { expect, test } from "vitest";
5 | import webExtension from "../../src/index";
6 | import { ViteWebExtensionOptions } from "../../types";
7 |
8 | type InputManifestGenerator = () => Partial;
9 |
10 | function normalizeFileName(fileName: string): string {
11 | return normalizePath(path.normalize(fileName));
12 | }
13 |
14 | async function bundleGenerate(
15 | options: ViteWebExtensionOptions
16 | ): Promise {
17 | const bundle = await build({
18 | logLevel: "warn",
19 | build: {
20 | write: false,
21 | minify: false,
22 | rollupOptions: {
23 | output: {
24 | entryFileNames: `assets/[name].js`,
25 | chunkFileNames: `assets/[name].js`,
26 | assetFileNames: `assets/[name].[ext]`,
27 | },
28 | },
29 | },
30 | plugins: [webExtension(options)],
31 | });
32 |
33 | return bundle as RollupOutput;
34 | }
35 |
36 | function trimFilePathToRepoDirectory(filePath: string): string {
37 | return filePath.substring(filePath.lastIndexOf("vite-plugin-web-extension"));
38 | }
39 |
40 | export async function runTest({
41 | manifestGenerator,
42 | manifestVersion,
43 | pluginOptions,
44 | }: {
45 | manifestVersion: ManifestType["manifest_version"];
46 | manifestGenerator: InputManifestGenerator;
47 | pluginOptions: Partial;
48 | }): Promise {
49 | const [repoDir] = __dirname.split("/test/manifest");
50 |
51 | const baseManifest: chrome.runtime.Manifest = {
52 | version: "1.0.0",
53 | name: "Manifest Name",
54 | manifest_version: manifestVersion,
55 | };
56 |
57 | let { output } = await bundleGenerate({
58 | manifest: {
59 | ...baseManifest,
60 | ...manifestGenerator(),
61 | },
62 | ...pluginOptions,
63 | });
64 |
65 | expect(
66 | output
67 | .map((file) => {
68 | if (file.type === "chunk") {
69 | const modules = {};
70 | for (const [key, value] of Object.entries(file.modules)) {
71 | modules[trimFilePathToRepoDirectory(key)] = value;
72 | }
73 |
74 | return {
75 | code: file.code,
76 | dynamicImports: file.dynamicImports,
77 | exports: file.exports,
78 | facadeModuleId: file.facadeModuleId
79 | ? trimFilePathToRepoDirectory(file.facadeModuleId)
80 | : null,
81 | fileName: normalizeFileName(file.fileName),
82 | implicitlyLoadedBefore: file.implicitlyLoadedBefore,
83 | importedBindings: file.importedBindings,
84 | imports: file.imports,
85 | isDynamicEntry: file.isDynamicEntry,
86 | isEntry: file.isEntry,
87 | isImplicitEntry: file.isImplicitEntry,
88 | map: file.map,
89 | modules: modules,
90 | name: normalizeFileName(file.name),
91 | referencedFiles: file.referencedFiles,
92 | type: file.type,
93 | viteMetadata: file.viteMetadata,
94 | };
95 | }
96 |
97 | if (file.type === "asset") {
98 | return {
99 | fileName: normalizeFileName(file.fileName),
100 | name:
101 | typeof file.name === "undefined"
102 | ? undefined
103 | : normalizeFileName(file.name),
104 | source: file.source,
105 | type: file.type,
106 | };
107 | }
108 |
109 | return file;
110 | })
111 | .sort((a, b) => a.fileName.localeCompare(b.fileName))
112 | ).toMatchSnapshot();
113 | }
114 |
115 | export function getResourceDir(path: string): string {
116 | return `test/manifest/resources/${path}`;
117 | }
118 |
119 | export async function runManifestV2Test(
120 | testName: string,
121 | manifestGenerator: InputManifestGenerator,
122 | pluginOptions: Partial = {}
123 | ) {
124 | test(`${testName} - Manifest V2`, async () => {
125 | await runTest({
126 | manifestVersion: 2,
127 | manifestGenerator,
128 | pluginOptions,
129 | });
130 | });
131 | }
132 |
133 | export async function runManifestV3Test(
134 | testName: string,
135 | manifestGenerator: InputManifestGenerator,
136 | pluginOptions: Partial = {}
137 | ) {
138 | test(`${testName} - Manifest V3`, async () => {
139 | await runTest({
140 | manifestVersion: 3,
141 | manifestGenerator,
142 | pluginOptions,
143 | });
144 | });
145 | }
146 |
--------------------------------------------------------------------------------
/test/manifest/optimizeWebAccessibleResourcesDisabled.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("optimizeWebAccessibleResources");
4 |
5 | runManifestV2Test(
6 | "optimizeWebAccessibleResourcesDisabled",
7 | () => ({
8 | content_scripts: [
9 | {
10 | js: [`${resourceDir}/content1.js`],
11 | matches: [""],
12 | },
13 | {
14 | js: [`${resourceDir}/content2.js`],
15 | matches: [""],
16 | },
17 | ],
18 | }),
19 | {
20 | additionalInputs: {
21 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
22 | },
23 | optimizeWebAccessibleResources: false,
24 | }
25 | );
26 |
--------------------------------------------------------------------------------
/test/manifest/optimizeWebAccessibleResourcesDisabled.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("optimizeWebAccessibleResources");
4 |
5 | runManifestV3Test(
6 | "optimizeWebAccessibleResourcesDisabled",
7 | () => ({
8 | content_scripts: [
9 | {
10 | js: [`${resourceDir}/content1.js`],
11 | matches: [""],
12 | },
13 | {
14 | js: [`${resourceDir}/content2.js`],
15 | matches: [""],
16 | },
17 | ],
18 | }),
19 | {
20 | additionalInputs: {
21 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
22 | },
23 | optimizeWebAccessibleResources: false,
24 | }
25 | );
26 |
--------------------------------------------------------------------------------
/test/manifest/optimizeWebAccessibleResourcesEnabled.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("optimizeWebAccessibleResources");
4 |
5 | runManifestV2Test(
6 | "optimizeWebAccessibleResourcesEnabled",
7 | () => ({
8 | content_scripts: [
9 | {
10 | js: [`${resourceDir}/content1.js`],
11 | matches: [""],
12 | },
13 | {
14 | js: [`${resourceDir}/content2.js`],
15 | matches: [""],
16 | },
17 | ],
18 | }),
19 | {
20 | additionalInputs: {
21 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
22 | },
23 | }
24 | );
25 |
--------------------------------------------------------------------------------
/test/manifest/optimizeWebAccessibleResourcesEnabled.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("optimizeWebAccessibleResources");
4 |
5 | runManifestV3Test(
6 | "optimizeWebAccessibleResourcesEnabled",
7 | () => ({
8 | content_scripts: [
9 | {
10 | js: [`${resourceDir}/content1.js`],
11 | matches: [""],
12 | },
13 | {
14 | js: [`${resourceDir}/content2.js`],
15 | matches: [""],
16 | },
17 | ],
18 | }),
19 | {
20 | additionalInputs: {
21 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
22 | },
23 | }
24 | );
25 |
--------------------------------------------------------------------------------
/test/manifest/optionsHtml.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("optionsHtml");
4 |
5 | runManifestV2Test("optionsHtml", () => ({
6 | options_ui: {
7 | page: `${resourceDir}/options.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/optionsHtml.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("optionsHtml");
4 |
5 | runManifestV3Test("optionsHtml", () => ({
6 | options_ui: {
7 | page: `${resourceDir}/options.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/popupHtml.v2.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV2Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("popupHtml");
4 |
5 | runManifestV2Test("popupHtml", () => ({
6 | browser_action: {
7 | default_popup: `${resourceDir}/popup.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/popupHtml.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("popupHtml");
4 |
5 | runManifestV3Test("popupHtml", () => ({
6 | action: {
7 | default_popup: `${resourceDir}/popup.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsHtml/html.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsHtml/script.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("webAccessible");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsHtml/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: red;
3 | }
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsScriptsChunkedImport/script1.js:
--------------------------------------------------------------------------------
1 | import log from "../shared/log";
2 |
3 | log("script1");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsScriptsChunkedImport/script2.js:
--------------------------------------------------------------------------------
1 | import log from "../shared/log";
2 |
3 | log("script2");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsScriptsNoImport/script1.js:
--------------------------------------------------------------------------------
1 | console.log("script1");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsScriptsNoImport/script2.js:
--------------------------------------------------------------------------------
1 | console.log("script2");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsScriptsTypes/script1.js:
--------------------------------------------------------------------------------
1 | console.log("script1");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsScriptsTypes/script2.ts:
--------------------------------------------------------------------------------
1 | console.log("script2");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsScriptsUnchunkedImport/script1.js:
--------------------------------------------------------------------------------
1 | import log from "../shared/log";
2 |
3 | log("script1");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsScriptsUnchunkedImport/script2.js:
--------------------------------------------------------------------------------
1 | console.log("script2");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsStylesTypes/style1.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: red;
3 | }
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsStylesTypes/style2.scss:
--------------------------------------------------------------------------------
1 | body {
2 | color: green;
3 | }
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsWebAccessible/chunkedScript1.js:
--------------------------------------------------------------------------------
1 | import log from "../shared/log";
2 |
3 | log("chunkedScript1");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsWebAccessible/chunkedScript2.js:
--------------------------------------------------------------------------------
1 | import log from "../shared/log";
2 |
3 | log("chunkedScript2");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsWebAccessible/chunkedScript3.js:
--------------------------------------------------------------------------------
1 | import log from "../shared/log";
2 |
3 | log("chunkedScript3");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsWebAccessible/script1.js:
--------------------------------------------------------------------------------
1 | console.log("script1");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsWebAccessible/script2.js:
--------------------------------------------------------------------------------
1 | console.log("script2");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsWebAccessible/script3.js:
--------------------------------------------------------------------------------
1 | console.log("script3");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsWebAccessible/script4.js:
--------------------------------------------------------------------------------
1 | console.log("script4");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsWebAccessible/script5.ts:
--------------------------------------------------------------------------------
1 | console.log("script5");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsWebAccessible/script6.js:
--------------------------------------------------------------------------------
1 | console.log("script6");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/additionalInputsWebAccessible/script7.js:
--------------------------------------------------------------------------------
1 | console.log("script7");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/backgroundHtml/background.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/backgroundHtml/background.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("background");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/backgroundScript/background.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/backgroundScript/background.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("background");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/backgroundServiceWorker/serviceWorker.js:
--------------------------------------------------------------------------------
1 | console.log("serviceWorker");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/chromeUrlOverridesHtml/bookmarks.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/chromeUrlOverridesHtml/chromeUrlOverridesHtml.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("chromeUrlOverridesHtml");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/chromeUrlOverridesHtml/devtools.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/chromeUrlOverridesHtml/history.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/chromeUrlOverridesHtml/newtab.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/chunkCssRewrite/content1.css:
--------------------------------------------------------------------------------
1 | #content1 {
2 | display: flex;
3 | }
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/chunkCssRewrite/content1.js:
--------------------------------------------------------------------------------
1 | import "./content1.css";
2 | import "./contentShared.css";
3 |
4 | console.log(import.meta.PLUGIN_WEB_EXT_CHUNK_CSS_PATHS);
5 |
--------------------------------------------------------------------------------
/test/manifest/resources/chunkCssRewrite/content2.css:
--------------------------------------------------------------------------------
1 | #content2 {
2 | display: flex;
3 | }
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/chunkCssRewrite/content2.js:
--------------------------------------------------------------------------------
1 | import "./content2.css";
2 | import "./contentShared.css";
3 |
4 | console.log(import.meta.PLUGIN_WEB_EXT_CHUNK_CSS_PATHS);
5 |
--------------------------------------------------------------------------------
/test/manifest/resources/chunkCssRewrite/contentNoCss.js:
--------------------------------------------------------------------------------
1 | console.log(import.meta.PLUGIN_WEB_EXT_CHUNK_CSS_PATHS);
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/chunkCssRewrite/contentShared.css:
--------------------------------------------------------------------------------
1 | #contentShared {
2 | display: flex;
3 | }
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentCss/content.js:
--------------------------------------------------------------------------------
1 | console.log("content");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentCss/content1.css:
--------------------------------------------------------------------------------
1 | .css {
2 | color: red;
3 | }
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentCss/content2.scss:
--------------------------------------------------------------------------------
1 | .css {
2 | color: green;
3 | }
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentScriptTypes/content1.js:
--------------------------------------------------------------------------------
1 | console.log("content1");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentScriptTypes/content2.ts:
--------------------------------------------------------------------------------
1 | console.log("content2");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentWithChunkedImport/content1.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("content");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentWithChunkedImport/content2.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("content2");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentWithDynamicImport/content1.js:
--------------------------------------------------------------------------------
1 | (async () => {
2 | const log = await import("./../shared/log");
3 |
4 | log("content");
5 | })();
6 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentWithDynamicImport/content2.js:
--------------------------------------------------------------------------------
1 | (async () => {
2 | const log = await import("./../shared/log");
3 |
4 | log("content2");
5 | })();
6 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentWithNoImports/content.js:
--------------------------------------------------------------------------------
1 | console.log("content");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentWithSameScriptName/content1/content.js:
--------------------------------------------------------------------------------
1 | console.log("content1");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentWithSameScriptName/content2/content.js:
--------------------------------------------------------------------------------
1 | console.log("content2");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/contentWithUnchunkedImport/content.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("content");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/devtoolsHtml/devtools.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/devtoolsHtml/devtools.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("devtools");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
13 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/entries/background/main.js:
--------------------------------------------------------------------------------
1 | browser.runtime.onInstalled.addListener(() => {
2 | console.log("Extension installed");
3 | });
4 |
5 | browser.action.onClicked.addListener(async () => {
6 | const tab = await getCurrentTab();
7 |
8 | chrome.scripting.executeScript({
9 | target: { tabId: tab?.id },
10 | files: ["src/lib.js"],
11 | });
12 | });
13 |
14 | async function getCurrentTab() {
15 | let queryOptions = { active: true, lastFocusedWindow: true };
16 | let [tab] = await chrome.tabs.query(queryOptions);
17 | return tab;
18 | }
19 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/entries/contentScript/primary/main.js:
--------------------------------------------------------------------------------
1 | import renderContent from "../renderContent";
2 | import logo from "../../../assets/logo.svg";
3 | import "./style.css";
4 |
5 | renderContent(import.meta.PLUGIN_WEB_EXT_CHUNK_CSS_PATHS, (appRoot) => {
6 | const logoImageUrl = new URL(logo, import.meta.url).href;
7 |
8 | appRoot.innerHTML = `
9 |
10 |

11 |
12 | `;
13 | });
14 |
15 | console.log(chrome.runtime.getURL("src/lib.js"));
16 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/entries/contentScript/primary/style.css:
--------------------------------------------------------------------------------
1 | .logo {
2 | z-index: 99999;
3 | position: fixed;
4 | bottom: 20px;
5 | right: 10px;
6 | width: 60px;
7 | height: 60px;
8 | display: flex;
9 | justify-content: center;
10 | align-items: center;
11 | border: 4px solid #c72a21;
12 | border-radius: 50%;
13 | background-color: #fff;
14 | }
15 |
16 | img {
17 | position: absolute;
18 | top: 7px;
19 | }
20 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/entries/contentScript/renderContent.js:
--------------------------------------------------------------------------------
1 | export default async function renderContent(
2 | cssPaths,
3 | render = (_appRoot) => {}
4 | ) {
5 | console.log("renderContent", cssPaths);
6 | }
7 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/entries/options/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Options
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/entries/options/main.js:
--------------------------------------------------------------------------------
1 | import logo from "../../assets/logo.svg";
2 | import "./style.css";
3 |
4 | const imageUrl = new URL(logo, import.meta.url).href;
5 |
6 | document.querySelector("#app").innerHTML = `
7 |
8 | Options
9 | Vite Docs
10 | `;
11 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/entries/options/style.css:
--------------------------------------------------------------------------------
1 | #app {
2 | font-family: Avenir, Helvetica, Arial, sans-serif;
3 | -webkit-font-smoothing: antialiased;
4 | -moz-osx-font-smoothing: grayscale;
5 | text-align: center;
6 | color: #2c3e50;
7 | }
8 |
9 | h1 {
10 | margin: 5px;
11 | }
12 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/entries/popup/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Popup
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/entries/popup/main.js:
--------------------------------------------------------------------------------
1 | import logo from "../../assets/logo.svg";
2 | import "./style.css";
3 |
4 | const imageUrl = new URL(logo, import.meta.url).href;
5 |
6 | document.querySelector("#app").innerHTML = `
7 |
8 | Popup
9 | Vite Docs
10 | `;
11 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/entries/popup/style.css:
--------------------------------------------------------------------------------
1 | #app {
2 | font-family: Avenir, Helvetica, Arial, sans-serif;
3 | -webkit-font-smoothing: antialiased;
4 | -moz-osx-font-smoothing: grayscale;
5 | text-align: center;
6 | color: #2c3e50;
7 | }
8 |
9 | h1 {
10 | margin: 5px;
11 | }
12 |
--------------------------------------------------------------------------------
/test/manifest/resources/fullExtension/src/lib.js:
--------------------------------------------------------------------------------
1 | console.log("lib.js");
2 |
--------------------------------------------------------------------------------
/test/manifest/resources/htmlUrlProperties/devtools.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/htmlUrlProperties/devtools.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("devtools");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/htmlUrlProperties/options.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/htmlUrlProperties/options.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("options");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/htmlUrlProperties/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/htmlUrlProperties/popup.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("popup");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/optimizeWebAccessibleResources/content1.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("content");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/optimizeWebAccessibleResources/content2.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("content2");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/optimizeWebAccessibleResources/script1.js:
--------------------------------------------------------------------------------
1 | import log from "../shared/log";
2 |
3 | log("script1");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/optimizeWebAccessibleResources/script2.js:
--------------------------------------------------------------------------------
1 | import log from "../shared/log";
2 |
3 | log("script2");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/optionsHtml/options.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/optionsHtml/options.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("options");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/popupHtml/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/popupHtml/popup.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("popup");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/shared/log.js:
--------------------------------------------------------------------------------
1 | export default function log(message) {
2 | console.log(message);
3 | }
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/sidePanelHtml/sidepanel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/manifest/resources/sidePanelHtml/sidepanel.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("sidepanel");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/useDynamicUrlWebAccessibleResources/content1.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("content");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/useDynamicUrlWebAccessibleResources/content2.js:
--------------------------------------------------------------------------------
1 | import log from "./../shared/log";
2 |
3 | log("content2");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/useDynamicUrlWebAccessibleResources/script1.js:
--------------------------------------------------------------------------------
1 | import log from "../shared/log";
2 |
3 | log("script1");
4 |
--------------------------------------------------------------------------------
/test/manifest/resources/useDynamicUrlWebAccessibleResources/script2.js:
--------------------------------------------------------------------------------
1 | import log from "../shared/log";
2 |
3 | log("script2");
4 |
--------------------------------------------------------------------------------
/test/manifest/sidePanelHtml.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("sidePanelHtml");
4 |
5 | runManifestV3Test("sidePanelHtml", () => ({
6 | side_panel: {
7 | default_path: `${resourceDir}/sidepanel.html`,
8 | },
9 | }));
10 |
--------------------------------------------------------------------------------
/test/manifest/useDynamicUrlWebAccessibleResourcesDisabled.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("useDynamicUrlWebAccessibleResources");
4 |
5 | runManifestV3Test(
6 | "useDynamicUrlWebAccessibleResourcesDisabled",
7 | () => ({
8 | content_scripts: [
9 | {
10 | js: [`${resourceDir}/content1.js`],
11 | matches: [""],
12 | },
13 | {
14 | js: [`${resourceDir}/content2.js`],
15 | matches: [""],
16 | },
17 | ],
18 | }),
19 | {
20 | additionalInputs: {
21 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
22 | },
23 | useDynamicUrlWebAccessibleResources: false,
24 | }
25 | );
26 |
--------------------------------------------------------------------------------
/test/manifest/useDynamicUrlWebAccessibleResourcesEnabled.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("useDynamicUrlWebAccessibleResources");
4 |
5 | runManifestV3Test(
6 | "useDynamicUrlWebAccessibleResourcesEnabled",
7 | () => ({
8 | content_scripts: [
9 | {
10 | js: [`${resourceDir}/content1.js`],
11 | matches: [""],
12 | },
13 | {
14 | js: [`${resourceDir}/content2.js`],
15 | matches: [""],
16 | },
17 | ],
18 | }),
19 | {
20 | additionalInputs: {
21 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
22 | },
23 | useDynamicUrlWebAccessibleResources: true,
24 | }
25 | );
26 |
--------------------------------------------------------------------------------
/test/manifest/useDynamicUrlWebAccessibleResourcesUndefined.v3.test.ts:
--------------------------------------------------------------------------------
1 | import { getResourceDir, runManifestV3Test } from "./manifestTestUtils";
2 |
3 | const resourceDir = getResourceDir("useDynamicUrlWebAccessibleResources");
4 |
5 | runManifestV3Test(
6 | "useDynamicUrlWebAccessibleResourcesEnabled",
7 | () => ({
8 | content_scripts: [
9 | {
10 | js: [`${resourceDir}/content1.js`],
11 | matches: [""],
12 | },
13 | {
14 | js: [`${resourceDir}/content2.js`],
15 | matches: [""],
16 | },
17 | ],
18 | }),
19 | {
20 | additionalInputs: {
21 | scripts: [`${resourceDir}/script1.js`, `${resourceDir}/script2.js`],
22 | },
23 | }
24 | );
25 |
--------------------------------------------------------------------------------
/test/utils/addHmrSupportToCsp.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from "vitest";
2 | import parse from "content-security-policy-parser";
3 |
4 | import { addHmrSupportToCsp } from "./../../src/utils/addHmrSupportToCsp";
5 |
6 | const basicCsp =
7 | "script-src 'self' https://app.foo.com; connect-src https://*.googleapis.com; image-src 'self'; object-src 'self'";
8 | const basicCspWithDupes =
9 | "script-src 'self' https://app.foo.com 'self'; connect-src https://*.googleapis.com; image-src 'self'; object-src 'none' 'none'";
10 |
11 | describe("Creating an HMR friendly CSP document", () => {
12 | it("should work without a passed in existing CSP", () => {
13 | const cspStr = addHmrSupportToCsp("http://localhost:5173", []);
14 | const csp = parse(cspStr);
15 |
16 | expect(csp["script-src"].length).toEqual(2);
17 | expect(csp["script-src"]).toContain("'self'");
18 | expect(csp["script-src"]).toContain("http://localhost:5173");
19 | expect(csp["object-src"].length).toEqual(1);
20 | expect(csp["object-src"]).toContain("'self'");
21 | });
22 | it("should let us pass in our own document", () => {
23 | const cspStr = addHmrSupportToCsp("http://localhost:5173", [], basicCsp);
24 | const csp = parse(cspStr);
25 |
26 | expect(csp["script-src"].length).toEqual(3);
27 | expect(csp["object-src"].length).toEqual(1);
28 | });
29 | it("should let us include inline hashes", () => {
30 | const cspStr = addHmrSupportToCsp(
31 | "http://localhost:5173",
32 | new Set([
33 | "sha256-B2yPHKaXnvFWtRChIbabYmUBFZdVfKKXHbWtWidDVF8=",
34 | "sha256-B2yPHKaXnvFWtRChIbabYmUBFZdVfKKXHbWtWidDVF7=",
35 | ]),
36 | basicCsp
37 | );
38 | const csp = parse(cspStr);
39 |
40 | expect(csp["script-src"].length).toEqual(5);
41 | });
42 |
43 | it("should let dedupe values", () => {
44 | const cspStr = addHmrSupportToCsp(
45 | "http://localhost:5173",
46 | new Set([
47 | "sha256-B2yPHKaXnvFWtRChIbabYmUBFZdVfKKXHbWtWidDVF8=",
48 | "sha256-B2yPHKaXnvFWtRChIbabYmUBFZdVfKKXHbWtWidDVF7=",
49 | ]),
50 | basicCspWithDupes
51 | );
52 | const csp = parse(cspStr);
53 |
54 | expect(csp["script-src"].length).toEqual(5);
55 | expect(csp["object-src"].length).toEqual(2);
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/test/utils/rollup.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from "vitest";
2 | import { addInputScriptsToOptionsInput } from "./../../src/utils/rollup";
3 |
4 | describe("Rollup Utils", () => {
5 | describe("addInputScriptsToOptionsInput", () => {
6 | it("Adds input scripts to string input", () => {
7 | expect(
8 | addInputScriptsToOptionsInput(
9 | [["outputFile.js", "inputFile.js"]],
10 | "src/index.js"
11 | )
12 | ).toEqual({
13 | "src/index.js": "src/index.js",
14 | "outputFile.js": "inputFile.js",
15 | });
16 | });
17 |
18 | it("Adds input scripts to array input", () => {
19 | expect(
20 | addInputScriptsToOptionsInput(
21 | [["outputFile.js", "inputFile.js"]],
22 | ["src/index.js", "src/index2.js"]
23 | )
24 | ).toEqual({
25 | "src/index.js": "src/index.js",
26 | "src/index2.js": "src/index2.js",
27 | "outputFile.js": "inputFile.js",
28 | });
29 | });
30 |
31 | it("Adds input scripts to empty options input object", () => {
32 | expect(
33 | addInputScriptsToOptionsInput([["outputFile.js", "inputFile.js"]], {})
34 | ).toEqual({
35 | "outputFile.js": "inputFile.js",
36 | });
37 | });
38 |
39 | it("Adds input scripts to options input object with existing entries", () => {
40 | expect(
41 | addInputScriptsToOptionsInput([["outputFile2.js", "inputFile2.js"]], {
42 | "outputFile.js": "inputFile.js",
43 | })
44 | ).toEqual({
45 | "outputFile.js": "inputFile.js",
46 | "outputFile2.js": "inputFile2.js",
47 | });
48 | });
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": true,
4 | "esModuleInterop": true,
5 | "lib": ["es2021"],
6 | "module": "esnext",
7 | "moduleResolution": "bundler",
8 | "noEmit": true,
9 | "noEmitOnError": false,
10 | "noUnusedLocals": true,
11 | "noUnusedParameters": true,
12 | "pretty": true,
13 | "sourceMap": true,
14 | "strict": true,
15 | "target": "es2021",
16 | "skipLibCheck": true
17 | },
18 | "exclude": ["dist", "node_modules", "test/types"],
19 | "include": ["src/**/*", "types/**/*"]
20 | }
21 |
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | import type { Plugin } from "vite";
2 |
3 | type WebAccessibleDefinition =
4 | | {
5 | matches: string[];
6 | extensionIds?: string[];
7 | excludeEntryFile?: boolean;
8 | }
9 | | {
10 | matches?: string[];
11 | extensionIds: string[];
12 | excludeEntryFile?: boolean;
13 | };
14 |
15 | type AdditionalInput =
16 | | string
17 | | {
18 | fileName: string;
19 | webAccessible: boolean | WebAccessibleDefinition;
20 | };
21 |
22 | type NormalizedAdditionalInput = {
23 | fileName: string;
24 | webAccessible: WebAccessibleDefinition | null;
25 | };
26 |
27 | export interface ViteWebExtensionOptions {
28 | /**
29 | * The manifest file to use as a base for the generated extension
30 | */
31 | manifest: chrome.runtime.Manifest;
32 |
33 | /**
34 | * Sets the use_dynamic_url property on web accessible resources generated by the plugin
35 | * Default: true
36 | */
37 | useDynamicUrlWebAccessibleResources?: boolean;
38 |
39 | /**
40 | * On build, in Manifest V3, merge web accessible resource definitions that have matching non-`resource` properties and dedupe and sort `resources`. In Manifest V2, sort web accessible resources.
41 | * Default: true
42 | */
43 | optimizeWebAccessibleResources?: boolean;
44 |
45 | /**
46 | * Additional input files that should be processed and treated as web extension inputs.
47 | * Useful for dynamically injected scripts and dynamically opened HTML pages.
48 | * The webAccessible option configures whether the entry file and its dependencies are included in the manifest `web_accessible_resources` property. Defaults to true.
49 | * When set to `true`, defaults to:
50 | ```ts
51 | {
52 | matches: [''],
53 | excludeEntryFile: false,
54 | }
55 | ```
56 | * The `excludeEntryFile` option prevents the entry file from being added as a web accessible resource. Defaults to false.
57 | */
58 | additionalInputs?: {
59 | scripts?: AdditionalInput[];
60 | html?: AdditionalInput[];
61 | styles?: AdditionalInput[];
62 | };
63 | }
64 |
65 | /**
66 | * Build cross platform, module-based web extensions using vite
67 | */
68 | export default function webExtension(options?: ViteWebExtensionOptions): Plugin;
69 |
--------------------------------------------------------------------------------