-
-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1894c07
commit b9a7f17
Showing
20 changed files
with
382 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
node_modules | ||
|
||
# testing | ||
coverage | ||
|
||
# production | ||
dist | ||
|
||
# misc | ||
.DS_Store | ||
|
||
# local env files | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
# lock files | ||
yarn.lock | ||
package-lock.json | ||
|
||
# debug files | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# extension.js | ||
extension-env.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
console.log('Hello from the background script!') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<script lang="ts"> | ||
let isDialogOpen = true; | ||
function setIsDialogOpen(value: boolean) { | ||
isDialogOpen = value; | ||
} | ||
</script> | ||
|
||
{#if isDialogOpen} | ||
<div> | ||
<div class="mx-auto max-w-7xl md:px-0 lg:p-6"> | ||
<div | ||
class="relative isolate overflow-hidden bg-gray-900 px-6 pt-16 shadow-2xl lg:rounded-3xl md:pt-24 md:h-full sm:h-[100vh] lg:flex lg:gap-x-20 lg:px-24 lg:pt-0" | ||
> | ||
<div | ||
class="absolute z-20 top-0 inset-x-0 flex justify-center overflow-hidden pointer-events-none" | ||
> | ||
<div class="w-[108rem] flex-none flex justify-end"> | ||
<picture> | ||
<img | ||
src="../images/tailwind_bg.png" | ||
alt="" | ||
class="w-[90rem] flex-none max-w-none hidden dark:block" | ||
decoding="async" | ||
/> | ||
</picture> | ||
</div> | ||
</div> | ||
<div | ||
class="mx-auto max-w-md text-center lg:py-12 lg:mx-0 lg:flex-auto lg:text-left" | ||
> | ||
<div | ||
class="flex items-center justify-center space-x-4 my-4 mx-auto" | ||
> | ||
<img | ||
alt="Svelte logo" | ||
src="../images/logo.svg" | ||
class="relative inline-block w-12" | ||
/> | ||
<div class="text-3xl text-white">+</div> | ||
<img | ||
alt="TypeScript logo" | ||
src="../images/typescript.png" | ||
class="relative inline-block w-12" | ||
/> | ||
<div class="text-3xl text-white">+</div> | ||
<img | ||
alt="Tailwind logo" | ||
src="../images/tailwind.png" | ||
class="relative inline-block w-12" | ||
/> | ||
</div> | ||
<h2 | ||
class="text-3xl font-bold tracking-tight text-white sm:text-4xl" | ||
> | ||
This is a content script running Svelte, TypeScript, and Tailwind.css | ||
</h2> | ||
<p class="mt-6 text-lg leading-8 text-gray-300"> | ||
Learn more about creating cross-browser extensions by | ||
<button | ||
on:click={() => setIsDialogOpen(false)} | ||
class="underline hover:no-underline" | ||
> | ||
closing this hint | ||
</button> | ||
. | ||
</p> | ||
</div> | ||
<div class="relative mt-16 h-80 lg:mt-8"> | ||
<img | ||
class="absolute left-0 top-0 w-[57rem] max-w-none rounded-md bg-white/5 ring-1 ring-white/10" | ||
src="../images/chromeWindow.png" | ||
alt="Chrome window screenshot" | ||
width="1824" | ||
height="1080" | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
{:else} | ||
<div class="mx-auto p-6"> | ||
<button | ||
on:click={() => setIsDialogOpen(true)} | ||
class="bg-white rounded-md p-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" | ||
> | ||
🧩 Open content script hint <span aria-hidden="true">+</span> | ||
</button> | ||
</div> | ||
{/if} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import * as svelte from 'svelte' | ||
import ContentApp from './ContentApp.svelte' | ||
import './styles.css?inline_style' | ||
|
||
function initial() { | ||
// Create a new div element and append it to the document's body | ||
const rootDiv = document.createElement('div') | ||
rootDiv.id = 'extension-root' | ||
document.body.appendChild(rootDiv) | ||
|
||
// Inject content_scripts inside a shadow DOM | ||
// to prevent conflicts with the host page's styles. | ||
const shadowRoot = rootDiv.attachShadow({mode: 'open'}) | ||
|
||
// @ts-expect-error - global reference. | ||
window.__EXTENSION_SHADOW_ROOT__ = shadowRoot | ||
|
||
// Create a container inside the shadow DOM for the Vue app | ||
const shadowAppContainer = document.createElement('div') | ||
shadowAppContainer.className = 'content_script' | ||
shadowRoot.appendChild(shadowAppContainer) | ||
|
||
// Mount the Vue app to the container inside the shadow DOM | ||
svelte.mount(ContentApp, { | ||
target: shadowAppContainer | ||
}) | ||
} | ||
|
||
// Initialize the app | ||
if (document.readyState === 'complete') { | ||
initial() | ||
} else { | ||
document.addEventListener('readystatechange', () => { | ||
if (document.readyState === 'complete') initial() | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
|
||
.content_script { | ||
position: fixed; | ||
bottom: 0; | ||
right: 0; | ||
z-index: 99999; | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"$schema": "https://json.schemastore.org/chrome-manifest.json", | ||
"manifest_version": 3, | ||
"version": "0.0.1", | ||
"name": "Content Scripts Svelte", | ||
"description": "An Extension.js example.", | ||
"icons": { | ||
"48": "images/extension_48.png" | ||
}, | ||
"permissions": ["activeTab", "scripting"], | ||
"host_permissions": ["<all_urls>"], | ||
"background": { | ||
"chromium:service_worker": "background.ts", | ||
"firefox:scripts": ["background.ts"] | ||
}, | ||
"content_scripts": [ | ||
{ | ||
"matches": ["<all_urls>"], | ||
"js": ["content/scripts.ts"] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"private": true, | ||
"name": "new-svelte", | ||
"description": "An Extension.js example.", | ||
"version": "0.0.1", | ||
"author": { | ||
"name": "Cezar Augusto", | ||
"email": "boss@cezaraugusto.net", | ||
"url": "https://cezaraugusto.com" | ||
}, | ||
"license": "MIT", | ||
"dependencies": { | ||
"svelte": "5.15.0", | ||
"tailwindcss": "^3.4.1" | ||
}, | ||
"devDependencies": { | ||
"@tsconfig/svelte": "5.0.4", | ||
"typescript": "5.3.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = { | ||
plugins: { | ||
tailwindcss: {}, | ||
autoprefixer: {} | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** @type {import('tailwindcss').Config} */ | ||
module.exports = { | ||
content: ['**/*.svelte'], | ||
theme: { | ||
extend: {} | ||
}, | ||
plugins: [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import path from 'path' | ||
import {execSync} from 'child_process' | ||
import {extensionFixtures, getShadowRootElement} from '../extension-fixtures' | ||
|
||
const exampleDir = 'examples/content-vue' | ||
const pathToExtension = path.join(__dirname, `dist/chrome`) | ||
const test = extensionFixtures(pathToExtension, true) | ||
|
||
test.beforeAll(async () => { | ||
execSync(`pnpm extension build ${exampleDir}`, { | ||
cwd: path.join(__dirname, '..') | ||
}) | ||
}) | ||
|
||
test('should exist an element with the class name extension-root', async ({ | ||
page | ||
}) => { | ||
await page.goto('https://extension.js.org/') | ||
const shadowRootHandle = await page | ||
.locator('#extension-root') | ||
.evaluateHandle((host: HTMLElement) => host.shadowRoot) | ||
|
||
// Validate that the Shadow DOM exists | ||
test.expect(shadowRootHandle).not.toBeNull() | ||
|
||
// Verify Shadow DOM has children | ||
const shadowChildrenCount = await shadowRootHandle.evaluate( | ||
(shadowRoot: ShadowRoot) => shadowRoot.children.length | ||
) | ||
test.expect(shadowChildrenCount).toBeGreaterThan(0) | ||
}) | ||
|
||
test('should exist an h2 element with specified content', async ({page}) => { | ||
await page.goto('https://extension.js.org/') | ||
const h2 = await getShadowRootElement(page, '#extension-root', 'h2') | ||
if (!h2) { | ||
throw new Error('h2 element not found in Shadow DOM') | ||
} | ||
const textContent = await h2.evaluate((node) => node.textContent) | ||
await test | ||
.expect(textContent) | ||
.toContain( | ||
'This is a content script running Vue, TypeScript, and Tailwind.css.' | ||
) | ||
}) | ||
|
||
test('should exist a default color value', async ({page}) => { | ||
await page.goto('https://extension.js.org/') | ||
const h2 = await getShadowRootElement(page, '#extension-root', 'h2') | ||
if (!h2) { | ||
throw new Error('h2 element not found in Shadow DOM') | ||
} | ||
const color = await h2.evaluate((node) => | ||
window.getComputedStyle(node as HTMLElement).getPropertyValue('color') | ||
) | ||
test.expect(color).toEqual('rgb(255, 255, 255)') | ||
}) | ||
|
||
test('should load all images successfully', async ({page}) => { | ||
await page.goto('https://extension.js.org/') | ||
const shadowRootHandle = await page | ||
.locator('#extension-root') | ||
.evaluateHandle((host: HTMLElement) => host.shadowRoot) | ||
|
||
const imagesHandle = await shadowRootHandle.evaluateHandle( | ||
(shadow: ShadowRoot) => Array.from(shadow.querySelectorAll('img')) | ||
) | ||
|
||
const imageHandles = await imagesHandle.getProperties() | ||
const results: boolean[] = [] | ||
|
||
for (const [, imageHandle] of imageHandles) { | ||
const naturalWidth = await imageHandle.evaluate( | ||
(img) => (img as HTMLImageElement).naturalWidth | ||
) | ||
const naturalHeight = await imageHandle.evaluate( | ||
(img) => (img as HTMLImageElement).naturalHeight | ||
) | ||
const loadedSuccessfully = naturalWidth > 0 && naturalHeight > 0 | ||
results.push(loadedSuccessfully) | ||
} | ||
|
||
test.expect(results.every((result) => result)).toBeTruthy() | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import path from 'path' | ||
import {execSync} from 'child_process' | ||
import {extensionFixtures, takeScreenshot} from '../extension-fixtures' | ||
|
||
const exampleDir = 'examples/new-svelte' | ||
const pathToExtension = path.join(__dirname, `dist/chrome`) | ||
const test = extensionFixtures(pathToExtension, true) | ||
|
||
test.beforeAll(async () => { | ||
execSync(`pnpm extension build ${exampleDir}`, { | ||
cwd: path.join(__dirname, '..') | ||
}) | ||
}) | ||
|
||
test('should exist an element with the welcome message text', async ({ | ||
page | ||
}) => { | ||
await page.goto('chrome://newtab/') | ||
const h1 = await page.waitForSelector('h1', { | ||
state: 'visible', | ||
timeout: 10000 | ||
}) | ||
const textContent = await h1.textContent() | ||
test.expect(textContent).toMatch(/Welcome to your/i) | ||
}) | ||
|
||
test('should exist a default color value', async ({page}) => { | ||
await page.goto('chrome://newtab/') | ||
const h1 = page.locator('h1') | ||
const color = await page.evaluate( | ||
(locator) => { | ||
return window.getComputedStyle(locator!).getPropertyValue('color') | ||
}, | ||
await h1.elementHandle() | ||
) | ||
test.expect(color).toEqual('rgb(201, 201, 201)') | ||
}) | ||
|
||
test.skip('takes a screenshot of the page', async ({page}) => { | ||
await page.goto('chrome://newtab/') | ||
await page.waitForSelector('h1') | ||
await takeScreenshot(page, path.join(__dirname, 'screenshot.png')) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"extends": "@tsconfig/svelte/tsconfig.json", | ||
"compilerOptions": { | ||
"allowJs": true, | ||
"allowSyntheticDefaultImports": true, | ||
"esModuleInterop": true, | ||
"forceConsistentCasingInFileNames": true, | ||
"isolatedModules": true, | ||
"jsx": "react-jsx", | ||
"lib": ["dom", "dom.iterable", "esnext"], | ||
"moduleResolution": "node", | ||
"module": "esnext", | ||
"noEmit": true, | ||
"resolveJsonModule": true, | ||
"strict": true, | ||
"target": "esnext", | ||
"verbatimModuleSyntax": true, | ||
"useDefineForClassFields": true, | ||
"skipLibCheck": true | ||
}, | ||
"include": ["./", "extension-env.d.ts"], | ||
"exclude": ["node_modules", "dist"] | ||
} |