Skip to content

Commit

Permalink
feat/injecting scripts from popup (#579)
Browse files Browse the repository at this point in the history
Co-authored-by: JongHak Seo <unqocn@gmail.com>
  • Loading branch information
PatrykKuniczak and Jonghakseo authored Jul 20, 2024
1 parent 71d8e1e commit 241f4f4
Show file tree
Hide file tree
Showing 15 changed files with 196 additions and 28 deletions.
3 changes: 2 additions & 1 deletion chrome-extension/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const manifest = deepmerge(
name: '__MSG_extensionName__',
version: packageJson.version,
description: '__MSG_extensionDescription__',
permissions: ['storage'],
host_permissions: ['<all_urls>'],
permissions: ['storage', 'scripting'],
options_page: 'options/index.html',
background: {
service_worker: 'background.iife.js',
Expand Down
10 changes: 5 additions & 5 deletions packages/shared/build.mjs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import * as esbuild from "esbuild"
import * as esbuild from 'esbuild';

/**
* @type { import("esbuild").BuildOptions }
*/
const buildOptions = {
entryPoints: ["./index.ts", "./lib/**/*.ts", "./lib/**/*.tsx"],
tsconfig: "./tsconfig.json",
entryPoints: ['./index.ts', './lib/**/*.ts', './lib/**/*.tsx'],
tsconfig: './tsconfig.json',
bundle: false,
target: 'es6',
outdir: "./dist",
outdir: './dist',
sourcemap: true,
}
};

await esbuild.build(buildOptions);
16 changes: 8 additions & 8 deletions packages/ui/build.mjs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import * as esbuild from "esbuild"
import * as fs from "fs";
import { resolve } from "node:path";
import * as esbuild from 'esbuild';
import * as fs from 'fs';
import { resolve } from 'node:path';

/**
* @type { import("esbuild").BuildOptions }
*/
const buildOptions = {
entryPoints: ["./index.ts","./tailwind.config.ts", "./lib/**/*.ts", "./lib/**/*.tsx"],
tsconfig: "./tsconfig.json",
entryPoints: ['./index.ts', './tailwind.config.ts', './lib/**/*.ts', './lib/**/*.tsx'],
tsconfig: './tsconfig.json',
bundle: false,
target: 'es6',
outdir: "./dist",
outdir: './dist',
sourcemap: true,
}
};

await esbuild.build(buildOptions);
fs.copyFileSync(resolve("lib", "global.css"),resolve("dist", "global.css"))
fs.copyFileSync(resolve('lib', 'global.css'), resolve('dist', 'global.css'));
9 changes: 9 additions & 0 deletions pages/content-runtime/lib/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useEffect } from 'react';

export default function App() {
useEffect(() => {
console.log('runtime content view loaded');
}, []);

return <div className="runtime-content-view-text">runtime content view</div>;
}
3 changes: 3 additions & 0 deletions pages/content-runtime/lib/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.runtime-content-view-text {
font-size: 20px;
}
11 changes: 11 additions & 0 deletions pages/content-runtime/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* DO NOT USE import someModule from '...';
*
* @issue-url https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite/issues/160
*
* Chrome extensions don't support modules in content scripts.
* If you want to use other modules in content scripts, you need to import them via these files.
*
*/
import('@lib/root');
console.log('runtime script loaded');
38 changes: 38 additions & 0 deletions pages/content-runtime/lib/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createRoot } from 'react-dom/client';
import App from '@lib/app';
// eslint-disable-next-line
// @ts-ignore
import injectedStyle from '@lib/index.css?inline';

const root = document.createElement('div');
root.id = 'chrome-extension-boilerplate-react-vite-runtime-content-view-root';

document.body.append(root);

const rootIntoShadow = document.createElement('div');
rootIntoShadow.id = 'shadow-root';

const shadowRoot = root.attachShadow({ mode: 'open' });
shadowRoot.appendChild(rootIntoShadow);

/** Inject styles into shadow dom */
const globalStyleSheet = new CSSStyleSheet();
globalStyleSheet.replaceSync(injectedStyle);
shadowRoot.adoptedStyleSheets = [globalStyleSheet];
shadowRoot.appendChild(rootIntoShadow);
/**
* In the firefox environment, the adoptedStyleSheets bug may prevent style from being applied properly.
*
* @url https://bugzilla.mozilla.org/show_bug.cgi?id=1770592
* @url https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite/pull/174
*
* Please refer to the links above and try the following code if you encounter the issue.
*
* ```ts
* const styleElement = document.createElement('style');
* styleElement.innerHTML = injectedStyle;
* shadowRoot.appendChild(styleElement);
* ```
*/

createRoot(rootIntoShadow).render(<App />);
26 changes: 26 additions & 0 deletions pages/content-runtime/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@chrome-extension-boilerplate/content-runtime-script",
"version": "0.0.1",
"description": "chrome extension content runtime script",
"private": true,
"sideEffects": true,
"files": [
"dist/**"
],
"scripts": {
"clean": "rimraf ./dist",
"build": "pnpm run clean && pnpm type-check && vite build",
"build:watch": "cross-env __DEV__=true vite build -w --mode development",
"dev": "pnpm build:watch",
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "pnpm lint --fix",
"prettier": "prettier . --write --ignore-path ../../.prettierignore",
"type-check": "tsc --noEmit"
},
"dependencies": {},
"devDependencies": {
"@chrome-extension-boilerplate/tsconfig": "workspace:*",
"@chrome-extension-boilerplate/hmr": "workspace:*",
"@chrome-extension-boilerplate/vite-config": "workspace:*"
}
}
11 changes: 11 additions & 0 deletions pages/content-runtime/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "@chrome-extension-boilerplate/tsconfig/base",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@lib/*": ["lib/*"]
},
"types": ["chrome"]
},
"include": ["lib"]
}
23 changes: 23 additions & 0 deletions pages/content-runtime/vite.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { resolve } from 'path';
import { withPageConfig } from '@chrome-extension-boilerplate/vite-config';

const rootDir = resolve(__dirname);
const libDir = resolve(rootDir, 'lib');

export default withPageConfig({
resolve: {
alias: {
'@lib': libDir,
},
},
publicDir: resolve(rootDir, 'public'),
build: {
lib: {
formats: ['iife'],
entry: resolve(__dirname, 'lib/index.ts'),
name: 'ContentRuntimeScript',
fileName: 'index',
},
outDir: resolve(rootDir, '..', '..', 'dist', 'content-runtime'),
},
});
15 changes: 14 additions & 1 deletion pages/content-ui/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,21 @@ shadowRoot.appendChild(rootIntoShadow);
/** Inject styles into shadow dom */
const globalStyleSheet = new CSSStyleSheet();
globalStyleSheet.replaceSync(tailwindcssOutput);

shadowRoot.adoptedStyleSheets = [globalStyleSheet];
shadowRoot.appendChild(rootIntoShadow);
/**
* In the firefox environment, the adoptedStyleSheets bug may prevent style from being applied properly.
*
* @url https://bugzilla.mozilla.org/show_bug.cgi?id=1770592
* @url https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite/pull/174
*
* Please refer to the links above and try the following code if you encounter the issue.
*
* const styleElement = document.createElement('style');
* styleElement.innerHTML = tailwindcssOutput;
* shadowRoot.appendChild(styleElement);
* ```
*/

createRoot(rootIntoShadow).render(<App />);
18 changes: 7 additions & 11 deletions pages/content-ui/src/tailwind-output.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@ html,
-moz-tab-size: 4;
/* 3 */
-o-tab-size: 4;
tab-size: 4;
tab-size: 4;
/* 3 */
font-family: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
/* 4 */
font-feature-settings: normal;
/* 5 */
Expand Down Expand Up @@ -90,7 +89,7 @@ Add the correct text decoration in Chrome, Edge, and Safari.

abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
text-decoration: underline dotted;
}

/*
Expand Down Expand Up @@ -136,7 +135,7 @@ code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
/* 1 */
font-feature-settings: normal;
/* 2 */
Expand Down Expand Up @@ -379,8 +378,7 @@ textarea {
2. Set the default placeholder color to the user's configured gray 400 color.
*/

input::-moz-placeholder,
textarea::-moz-placeholder {
input::-moz-placeholder, textarea::-moz-placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
Expand All @@ -400,7 +398,7 @@ Set the default cursor for buttons.
*/

button,
[role='button'] {
[role="button"] {
cursor: pointer;
}

Expand Down Expand Up @@ -448,9 +446,7 @@ video {
display: none;
}

*,
::before,
::after {
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
Expand Down
4 changes: 3 additions & 1 deletion pages/popup/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
},
"dependencies": {
"@chrome-extension-boilerplate/shared": "workspace:*",
"@chrome-extension-boilerplate/storage": "workspace:*"
"@chrome-extension-boilerplate/storage": "workspace:*",
"@chrome-extension-boilerplate/content-runtime-script": "workspace:*",
"@types/node": "^20.14.10"
},
"devDependencies": {
"@chrome-extension-boilerplate/tailwindcss-config": "workspace:*",
Expand Down
19 changes: 18 additions & 1 deletion pages/popup/src/Popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,30 @@ const Popup = () => {
const isLight = theme === 'light';
const logo = isLight ? 'popup/logo_vertical.svg' : 'popup/logo_vertical_dark.svg';

const injectContentScript = async () => {
const [tab] = await chrome.tabs.query({ currentWindow: true, active: true });

await chrome.scripting.executeScript({
target: { tabId: tab.id! },
files: ['content-runtime/index.iife.js'],
});
};

return (
<div className={`App ${isLight ? 'bg-slate-50' : 'bg-gray-800'}`}>
<header className={`App-header ${isLight ? 'text-gray-900' : 'text-gray-100'}`}>
<img src={chrome.runtime.getURL(logo)} className="App-logo" alt="logo" />
<p>
Edit <code>pages/popup/src/Popup.tsx</code>
</p>
<button
className={
'font-bold mt-4 py-1 px-4 rounded shadow hover:scale-105 ' +
(isLight ? 'bg-blue-200 text-black' : 'bg-gray-700 text-white')
}
onClick={injectContentScript}>
Click to inject Content Script
</button>
<ToggleButton>Toggle theme</ToggleButton>
</header>
</div>
Expand All @@ -29,7 +46,7 @@ const ToggleButton = (props: ComponentPropsWithoutRef<'button'>) => {
props.className +
' ' +
'font-bold mt-4 py-1 px-4 rounded shadow hover:scale-105 ' +
(theme === 'light' ? 'bg-white text-black' : 'bg-black text-white')
(theme === 'light' ? 'bg-white text-black shadow-black' : 'bg-black text-white')
}
onClick={exampleThemeStorage.toggle}>
{props.children}
Expand Down
18 changes: 18 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 241f4f4

Please sign in to comment.