chore(all): improve some configuration and template code
This commit is contained in:
parent
d5d8c60e53
commit
1b04f94ee2
17 changed files with 2508 additions and 145 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,9 +1,8 @@
|
|||
dist
|
||||
node_modules
|
||||
|
||||
.DS_Store
|
||||
.eslintcache
|
||||
|
||||
*.DS_Store
|
||||
*.eslintcache
|
||||
*.crx
|
||||
*.local
|
||||
*.log
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
pnpm lint-staged
|
||||
pnpm lint-staged && pnpm tsc:check
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# [WIP]WebChat
|
||||
# [WIP] WebChat
|
||||
|
||||
> Chatting Anonymously with People on the Same Website.
|
||||
|
|
3
env.d.ts
vendored
Normal file
3
env.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
declare const __DEV__: boolean
|
||||
/** Extension name, defined in packageJson.name */
|
||||
declare const __NAME__: string
|
10
manifest.ts
10
manifest.ts
|
@ -1,14 +1,14 @@
|
|||
import { defineManifest } from '@crxjs/vite-plugin'
|
||||
import pkgJson from './package.json'
|
||||
import packageJson from './package.json'
|
||||
|
||||
export default defineManifest({
|
||||
manifest_version: 3,
|
||||
name: pkgJson.displayName,
|
||||
version: pkgJson.version,
|
||||
name: packageJson.displayName,
|
||||
version: packageJson.version,
|
||||
content_scripts: [
|
||||
{
|
||||
js: ['src/content/main.tsx'],
|
||||
matches: ['*://www.example.com//*']
|
||||
js: ['src/main.tsx'],
|
||||
matches: ['*://www.example.com/*']
|
||||
}
|
||||
]
|
||||
})
|
||||
|
|
15
package.json
15
package.json
|
@ -5,7 +5,13 @@
|
|||
"description": "Chatting Anonymously with People on the Same Website.",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"pack": "cross-env NODE_ENV=production run-p pack:*",
|
||||
"pack:zip": "rimraf dist.zip && jszip-cli add dist/* -o ./dist.zip",
|
||||
"pack:crx": "crx pack dist -o ./dist.crx",
|
||||
"pack:xpi": "cross-env WEB_EXT_ARTIFACTS_DIR=./ web-ext build --source-dir ./dist --filename dist.xpi --overwrite-dest",
|
||||
"lint": "npx eslint . --ext .js,.jsx,.ts,.tsx --cache --fix",
|
||||
"clear": "rimraf dist dist.*",
|
||||
"tsc:check": "tsc --noEmit",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
|
@ -27,6 +33,7 @@
|
|||
"@commitlint/cli": "^17.6.6",
|
||||
"@commitlint/config-conventional": "^17.6.6",
|
||||
"@crxjs/vite-plugin": "1.0.14",
|
||||
"@ffflorian/jszip-cli": "^3.4.1",
|
||||
"@iconify/json": "^2.2.90",
|
||||
"@svgr/core": "^8.0.0",
|
||||
"@svgr/plugin-jsx": "^8.0.1",
|
||||
|
@ -36,6 +43,8 @@
|
|||
"@types/webextension-polyfill": "^0.10.1",
|
||||
"@vitejs/plugin-react": "^4.0.3",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"cross-env": "^7.0.3",
|
||||
"crx": "^5.0.1",
|
||||
"eslint": "^8.44.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-config-standard-with-typescript": "^36.0.0",
|
||||
|
@ -47,14 +56,17 @@
|
|||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"husky": "^8.0.3",
|
||||
"lint-staged": "^13.2.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^8.4.25",
|
||||
"prettier": "^3.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"rimraf": "^5.0.1",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"typescript": "^5.1.6",
|
||||
"unplugin-icons": "^0.16.5",
|
||||
"vite": "^4.4.3",
|
||||
"web-ext": "^7.6.2",
|
||||
"webext-bridge": "^6.0.1",
|
||||
"webextension-polyfill": "^0.10.0"
|
||||
},
|
||||
|
@ -66,6 +78,7 @@
|
|||
"class-variance-authority": "^0.6.1",
|
||||
"clsx": "^1.2.1",
|
||||
"tailwind-merge": "^1.13.2",
|
||||
"tailwindcss-animate": "^1.0.6"
|
||||
"tailwindcss-animate": "^1.0.6",
|
||||
"type-fest": "^3.13.0"
|
||||
}
|
||||
}
|
||||
|
|
2438
pnpm-lock.yaml
2438
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
10
shim.d.ts
vendored
10
shim.d.ts
vendored
|
@ -1,10 +0,0 @@
|
|||
import type { ProtocolWithReturn } from 'webext-bridge'
|
||||
|
||||
declare module 'webext-bridge' {
|
||||
export interface ProtocolMap {
|
||||
// define message protocol types
|
||||
// see https://github.com/antfu/webext-bridge#type-safe-protocols
|
||||
'tab-prev': { title: string | undefined }
|
||||
'get-current-tab': ProtocolWithReturn<{ tabId: number }, { title?: string }>
|
||||
}
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
import { useState } from 'react'
|
||||
import IconPower from '~icons/pixelarticons/power'
|
||||
|
||||
import Sidebar from './Sidebar'
|
||||
import Sidebar from '@/components/Sidebar'
|
||||
|
||||
export default function App() {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [openedOnce, setOpenedOnce] = useState(false)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<div className="fixed left-0 bottom-0 m-5 z-100 flex font-sans select-none leading-1em">
|
||||
<div
|
||||
className="flex justify-center items-center w-10 h-10 rounded-full shadow cursor-pointer bg-blue-400 hover:bg-blue-600"
|
||||
|
@ -29,6 +29,6 @@ export default function App() {
|
|||
<Sidebar></Sidebar>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import createElement from '@/utils'
|
||||
import { type ReactNode } from 'react'
|
||||
import { createRoot, type Root } from 'react-dom/client'
|
||||
|
||||
export interface RootOptions {
|
||||
name: string
|
||||
mode?: ShadowRootMode
|
||||
css?: string
|
||||
}
|
||||
|
||||
const createShadowRoot = (options: RootOptions): Root => {
|
||||
const { name, mode = 'open', css = '' } = options
|
||||
const shadowRoot = createElement(`<${name}></${name}>`)
|
||||
const appStyle = createElement(`<style type="text/css">${css}</style>`)
|
||||
const appRoot = createElement(`<div id="app"></div>`)
|
||||
const reactRoot = createRoot(appRoot)
|
||||
|
||||
class WebChat extends HTMLElement {
|
||||
constructor() {
|
||||
super()
|
||||
const shadow = this.attachShadow({ mode })
|
||||
shadow.append(appStyle, appRoot)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...reactRoot,
|
||||
render: (children: ReactNode) => {
|
||||
customElements.define(name, WebChat)
|
||||
document.body.appendChild(shadowRoot)
|
||||
reactRoot.render(children)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default createShadowRoot
|
31
src/createShadowRoot.ts
Normal file
31
src/createShadowRoot.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { createElement } from '@/utils'
|
||||
import { type ReactNode } from 'react'
|
||||
import { createRoot, type Root } from 'react-dom/client'
|
||||
|
||||
export interface RootOptions {
|
||||
mode?: ShadowRootMode
|
||||
style?: string
|
||||
script?: string
|
||||
}
|
||||
|
||||
const createShadowRoot = (name: string, options: RootOptions): Root => {
|
||||
const { mode = 'open', style = '', script = '' } = options ?? {}
|
||||
const shadowApp = createElement(`<${name}></${name}>`)
|
||||
const shadowRoot = shadowApp.attachShadow({ mode })
|
||||
const appRoot = createElement(`<div id="app"></div>`)
|
||||
const appStyle = style && createElement(`<style type="text/css">${style}</style>`)
|
||||
const appScript = script && createElement(`<script type="application/javascript">${script}</script>`)
|
||||
const reactRoot = createRoot(appRoot)
|
||||
|
||||
shadowRoot.append(appStyle, appRoot, appScript)
|
||||
|
||||
return {
|
||||
...reactRoot,
|
||||
render: (children: ReactNode) => {
|
||||
document.body.appendChild(shadowApp)
|
||||
reactRoot.render(children)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default createShadowRoot
|
|
@ -2,10 +2,10 @@ import React from 'react'
|
|||
import App from './App'
|
||||
import createShadowRoot from './createShadowRoot'
|
||||
|
||||
import css from './main.css?inline'
|
||||
import style from './index.css?inline'
|
||||
|
||||
void (() => {
|
||||
createShadowRoot({ name: 'web-chat', css }).render(
|
||||
createShadowRoot(__NAME__, { style, mode: __DEV__ ? 'open' : 'closed' }).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
|
@ -1,78 +0,0 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
|
||||
--ring: 215 20.2% 65.1%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
|
||||
--muted: 217.2 32.6% 17.5%;
|
||||
--muted-foreground: 215 20.2% 65.1%;
|
||||
|
||||
--popover: 222.2 84% 4.9%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
|
||||
--card: 222.2 84% 4.9%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
|
||||
--border: 217.2 32.6% 17.5%;
|
||||
--input: 217.2 32.6% 17.5%;
|
||||
|
||||
--primary: 210 40% 98%;
|
||||
--primary-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--secondary: 217.2 32.6% 17.5%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
|
||||
--accent: 217.2 32.6% 17.5%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 85.7% 97.3%;
|
||||
|
||||
--ring: 217.2 32.6% 17.5%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,10 @@
|
|||
import { type ClassValue, clsx } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
export const cn = (...inputs: ClassValue[]) => {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
const createElement = <T extends Element>(template: string) => {
|
||||
export const createElement = <T extends Element>(template: string) => {
|
||||
return new Range().createContextualFragment(template).firstElementChild as unknown as T
|
||||
}
|
||||
|
||||
export default createElement
|
||||
|
|
|
@ -4,13 +4,18 @@ import react from '@vitejs/plugin-react'
|
|||
import { crx } from '@crxjs/vite-plugin'
|
||||
import Icons from 'unplugin-icons/vite'
|
||||
import manifest from './manifest'
|
||||
import packageJson from './package.json'
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, 'src')
|
||||
'@': path.resolve(__dirname, './src')
|
||||
}
|
||||
},
|
||||
define: {
|
||||
__DEV__: process.env.NODE_ENV !== 'production',
|
||||
__NAME__: JSON.stringify(packageJson.name)
|
||||
},
|
||||
plugins: [
|
||||
react(),
|
||||
// https://github.com/antfu/unplugin-icons
|
||||
|
|
Loading…
Reference in a new issue