@zhiwu215/code-template 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/index.js +59 -0
- package/package.json +38 -0
- package/src/frameworks/electron-vite.js +107 -0
- package/src/utils/renderTemplate.js +58 -0
- package/templates/electron-vite/plugins/shadcn/components.json +21 -0
- package/templates/electron-vite/plugins/shadcn/package.json +13 -0
- package/templates/electron-vite/plugins/shadcn/src/renderer/src/assets/globals.css +125 -0
- package/templates/electron-vite/plugins/shadcn/src/renderer/src/lib/utils.ts +6 -0
- package/templates/electron-vite/plugins/tailwind/electron.vite.config.ts +21 -0
- package/templates/electron-vite/plugins/tailwind/package.json +6 -0
- package/templates/electron-vite/plugins/tailwind/src/renderer/src/assets/globals.css +1 -0
- package/templates/electron-vite/plugins/tailwind/src/renderer/src/main.tsx +11 -0
- package/templates/electron-vite/plugins/zustand/package.json +5 -0
- package/templates/electron-vite/plugins/zustand/src/renderer/src/store/index.ts +1 -0
- package/templates/electron-vite/plugins/zustand/src/renderer/src/store/useAppStore.ts +18 -0
- package/templates/electron-vite/react/.editorconfig +9 -0
- package/templates/electron-vite/react/.prettierignore +6 -0
- package/templates/electron-vite/react/.prettierrc.yaml +4 -0
- package/templates/electron-vite/react/.vscode/extensions.json +3 -0
- package/templates/electron-vite/react/.vscode/launch.json +39 -0
- package/templates/electron-vite/react/.vscode/settings.json +11 -0
- package/templates/electron-vite/react/README.md +34 -0
- package/templates/electron-vite/react/build/entitlements.mac.plist +12 -0
- package/templates/electron-vite/react/build/icon.icns +0 -0
- package/templates/electron-vite/react/build/icon.ico +0 -0
- package/templates/electron-vite/react/build/icon.png +0 -0
- package/templates/electron-vite/react/dev-app-update.yml +3 -0
- package/templates/electron-vite/react/electron-builder.yml +43 -0
- package/templates/electron-vite/react/electron.vite.config.ts +16 -0
- package/templates/electron-vite/react/eslint.config.mjs +32 -0
- package/templates/electron-vite/react/package.json +56 -0
- package/templates/electron-vite/react/pnpm-workspace.yaml +4 -0
- package/templates/electron-vite/react/resources/icon.png +0 -0
- package/templates/electron-vite/react/src/main/index.ts +72 -0
- package/templates/electron-vite/react/src/preload/index.d.ts +8 -0
- package/templates/electron-vite/react/src/preload/index.ts +22 -0
- package/templates/electron-vite/react/src/renderer/index.html +17 -0
- package/templates/electron-vite/react/src/renderer/src/App.tsx +5 -0
- package/templates/electron-vite/react/src/renderer/src/env.d.ts +1 -0
- package/templates/electron-vite/react/src/renderer/src/main.tsx +9 -0
- package/templates/electron-vite/react/tsconfig.json +4 -0
- package/templates/electron-vite/react/tsconfig.node.json +8 -0
- package/templates/electron-vite/react/tsconfig.web.json +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 知兀
|
|
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.
|
package/index.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as p from '@clack/prompts'
|
|
3
|
+
import color from 'picocolors'
|
|
4
|
+
import fs from 'fs'
|
|
5
|
+
import path from 'path'
|
|
6
|
+
import { createElectronVite } from './src/frameworks/electron-vite.js'
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
console.clear()
|
|
10
|
+
p.intro(color.bgCyan(color.black(' 专属脚手架开发工具 ')))
|
|
11
|
+
|
|
12
|
+
// 1. 收集全局通用参数:项目名称与项目类型
|
|
13
|
+
const globalConfig = await p.group(
|
|
14
|
+
{
|
|
15
|
+
projectName: () =>
|
|
16
|
+
p.text({
|
|
17
|
+
message: '请输入项目名称:',
|
|
18
|
+
placeholder: 'my-app',
|
|
19
|
+
defaultValue: 'my-app',
|
|
20
|
+
validate: (val) => {
|
|
21
|
+
const name = val.trim()
|
|
22
|
+
if (!name) return '项目名称不能为空'
|
|
23
|
+
if (fs.existsSync(path.resolve(process.cwd(), name))) {
|
|
24
|
+
return `目录 "${name}" 已存在,请换一个名称`
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}),
|
|
28
|
+
|
|
29
|
+
toolchain: () =>
|
|
30
|
+
p.select({
|
|
31
|
+
message: '请选择项目生态体系:',
|
|
32
|
+
options: [
|
|
33
|
+
{ value: 'electron-vite', label: 'Electron 桌面应用 (基于 electron-vite)' }
|
|
34
|
+
]
|
|
35
|
+
})
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
onCancel: () => {
|
|
39
|
+
p.cancel('已取消创建。')
|
|
40
|
+
process.exit(0)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
const projectName = globalConfig.projectName.trim()
|
|
46
|
+
const targetDir = path.resolve(process.cwd(), projectName)
|
|
47
|
+
|
|
48
|
+
// 2. 路由分发给对应的具体框架模块处理
|
|
49
|
+
switch (globalConfig.toolchain) {
|
|
50
|
+
case 'electron-vite':
|
|
51
|
+
await createElectronVite(projectName, targetDir)
|
|
52
|
+
break
|
|
53
|
+
default:
|
|
54
|
+
p.cancel('未知的项目类型')
|
|
55
|
+
process.exit(1)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
main()
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zhiwu215/code-template",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "专属脚手架与项目模板开发工具",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"code-template": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.js",
|
|
12
|
+
"src",
|
|
13
|
+
"templates"
|
|
14
|
+
],
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/zhiwu215/code-template.git"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"scaffold",
|
|
24
|
+
"template",
|
|
25
|
+
"electron-vite",
|
|
26
|
+
"react",
|
|
27
|
+
"tailwind",
|
|
28
|
+
"shadcn",
|
|
29
|
+
"zustand"
|
|
30
|
+
],
|
|
31
|
+
"author": "zhiwu215",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@clack/prompts": "^0.9.0",
|
|
35
|
+
"picocolors": "^1.1.1"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as p from '@clack/prompts'
|
|
2
|
+
import color from 'picocolors'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import { fileURLToPath } from 'url'
|
|
6
|
+
import { renderTemplate } from '../utils/renderTemplate.js'
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const ROOT_DIR = path.resolve(__dirname, '..', '..')
|
|
10
|
+
const TEMPLATES_DIR = path.resolve(ROOT_DIR, 'templates', 'electron-vite')
|
|
11
|
+
const REACT_BASE_DIR = path.resolve(TEMPLATES_DIR, 'react')
|
|
12
|
+
const PLUGINS_DIR = path.resolve(TEMPLATES_DIR, 'plugins')
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 负责 electron-vite 项目的创建与组装
|
|
16
|
+
* @param {string} projectName 项目名称
|
|
17
|
+
* @param {string} targetDir 目标创建路径
|
|
18
|
+
*/
|
|
19
|
+
export async function createElectronVite(projectName, targetDir) {
|
|
20
|
+
const options = await p.group(
|
|
21
|
+
{
|
|
22
|
+
framework: () =>
|
|
23
|
+
p.select({
|
|
24
|
+
message: '请选择前端框架:',
|
|
25
|
+
options: [
|
|
26
|
+
{ value: 'react', label: 'React + TypeScript' }
|
|
27
|
+
]
|
|
28
|
+
}),
|
|
29
|
+
|
|
30
|
+
css: () =>
|
|
31
|
+
p.select({
|
|
32
|
+
message: '请选择 CSS 样式方案:',
|
|
33
|
+
options: [
|
|
34
|
+
{ value: 'tailwind', label: 'Tailwind CSS (v4)' },
|
|
35
|
+
{ value: 'none', label: '无 (原生 CSS)' }
|
|
36
|
+
]
|
|
37
|
+
}),
|
|
38
|
+
|
|
39
|
+
ui: () =>
|
|
40
|
+
p.select({
|
|
41
|
+
message: '请选择 UI 组件库:',
|
|
42
|
+
options: [
|
|
43
|
+
{ value: 'shadcn', label: 'shadcn/ui' },
|
|
44
|
+
{ value: 'none', label: '无 (不添加 UI 库)' }
|
|
45
|
+
]
|
|
46
|
+
}),
|
|
47
|
+
|
|
48
|
+
stateManagement: () =>
|
|
49
|
+
p.select({
|
|
50
|
+
message: '请选择状态管理方案:',
|
|
51
|
+
options: [
|
|
52
|
+
{ value: 'zustand', label: 'Zustand (轻量响应式状态管理)' },
|
|
53
|
+
{ value: 'none', label: '无 (不添加状态管理库)' }
|
|
54
|
+
]
|
|
55
|
+
})
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
onCancel: () => {
|
|
59
|
+
p.cancel('已取消创建。')
|
|
60
|
+
process.exit(0)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
const s = p.spinner()
|
|
66
|
+
|
|
67
|
+
// 1. 渲染基础底座
|
|
68
|
+
s.start(`正在初始化项目底座: ${color.cyan(projectName)}...`)
|
|
69
|
+
renderTemplate(REACT_BASE_DIR, targetDir)
|
|
70
|
+
|
|
71
|
+
// 更新目标 package.json 项目名称
|
|
72
|
+
const pkgPath = path.join(targetDir, 'package.json')
|
|
73
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
|
|
74
|
+
pkg.name = projectName
|
|
75
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8')
|
|
76
|
+
s.stop('项目底座初始化完毕')
|
|
77
|
+
|
|
78
|
+
// 2. 智能依赖计算:如果选了 shadcn/ui,自动补齐前置依赖 Tailwind CSS
|
|
79
|
+
const needsTailwind = options.css === 'tailwind' || options.ui === 'shadcn'
|
|
80
|
+
|
|
81
|
+
if (needsTailwind) {
|
|
82
|
+
s.start('正在配置 Tailwind CSS...')
|
|
83
|
+
renderTemplate(path.join(PLUGINS_DIR, 'tailwind'), targetDir)
|
|
84
|
+
s.stop('Tailwind CSS 配置完成')
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 3. 叠加 shadcn/ui
|
|
88
|
+
if (options.ui === 'shadcn') {
|
|
89
|
+
s.start('正在配置 shadcn/ui...')
|
|
90
|
+
renderTemplate(path.join(PLUGINS_DIR, 'shadcn'), targetDir)
|
|
91
|
+
s.stop('shadcn/ui 配置完成')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 4. 叠加 Zustand 状态管理
|
|
95
|
+
if (options.stateManagement === 'zustand') {
|
|
96
|
+
s.start('正在配置 Zustand 状态管理...')
|
|
97
|
+
renderTemplate(path.join(PLUGINS_DIR, 'zustand'), targetDir)
|
|
98
|
+
s.stop('Zustand 配置完成')
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 5. 交付提示(秒级完成,由用户自行按需安装依赖)
|
|
102
|
+
p.outro(color.green('项目创建成功!'))
|
|
103
|
+
console.log('\n接下来请运行以下命令启动项目:')
|
|
104
|
+
console.log(color.cyan(` cd ${projectName}`))
|
|
105
|
+
console.log(color.cyan(' pnpm install (或 npm install / yarn install)'))
|
|
106
|
+
console.log(color.cyan(' pnpm dev (或 npm run dev / yarn dev)\n'))
|
|
107
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 递归模板渲染与覆盖引擎
|
|
6
|
+
* @param {string} src 源目录
|
|
7
|
+
* @param {string} dest 目标目录
|
|
8
|
+
*/
|
|
9
|
+
export function renderTemplate(src, dest) {
|
|
10
|
+
const stats = fs.statSync(src)
|
|
11
|
+
|
|
12
|
+
if (stats.isDirectory()) {
|
|
13
|
+
if (['node_modules', 'pnpm-lock.yaml', 'package-lock.json', 'yarn.lock'].includes(path.basename(src))) return
|
|
14
|
+
fs.mkdirSync(dest, { recursive: true })
|
|
15
|
+
for (const file of fs.readdirSync(src)) {
|
|
16
|
+
renderTemplate(path.resolve(src, file), path.resolve(dest, file))
|
|
17
|
+
}
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const filename = path.basename(src)
|
|
22
|
+
|
|
23
|
+
// 遇到 package.json 执行智能深度合并
|
|
24
|
+
if (filename === 'package.json' && fs.existsSync(dest)) {
|
|
25
|
+
const existingPkg = JSON.parse(fs.readFileSync(dest, 'utf-8'))
|
|
26
|
+
const newPkg = JSON.parse(fs.readFileSync(src, 'utf-8'))
|
|
27
|
+
const merged = deepMerge(existingPkg, newPkg)
|
|
28
|
+
fs.writeFileSync(dest, JSON.stringify(merged, null, 2) + '\n', 'utf-8')
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 普通文件直接覆盖
|
|
33
|
+
fs.copyFileSync(src, dest)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 递归合并两个 JavaScript 对象(专用于 package.json)
|
|
38
|
+
*/
|
|
39
|
+
export function deepMerge(target, source) {
|
|
40
|
+
const result = { ...target }
|
|
41
|
+
for (const key of Object.keys(source)) {
|
|
42
|
+
const oldVal = result[key]
|
|
43
|
+
const newVal = source[key]
|
|
44
|
+
|
|
45
|
+
if (Array.isArray(oldVal) && Array.isArray(newVal)) {
|
|
46
|
+
result[key] = Array.from(new Set([...oldVal, ...newVal]))
|
|
47
|
+
} else if (
|
|
48
|
+
oldVal && typeof oldVal === 'object' &&
|
|
49
|
+
newVal && typeof newVal === 'object' &&
|
|
50
|
+
!Array.isArray(oldVal) && !Array.isArray(newVal)
|
|
51
|
+
) {
|
|
52
|
+
result[key] = deepMerge(oldVal, newVal)
|
|
53
|
+
} else {
|
|
54
|
+
result[key] = newVal
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return result
|
|
58
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "base-nova",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "@renderer/assets/globals.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"aliases": {
|
|
14
|
+
"components": "@renderer/components",
|
|
15
|
+
"utils": "@renderer/lib/utils",
|
|
16
|
+
"ui": "@renderer/components/ui",
|
|
17
|
+
"lib": "@renderer/lib",
|
|
18
|
+
"hooks": "@renderer/hooks"
|
|
19
|
+
},
|
|
20
|
+
"iconLibrary": "lucide"
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
4
|
+
"tailwindcss": "^4.3.3",
|
|
5
|
+
"class-variance-authority": "^0.7.1",
|
|
6
|
+
"clsx": "^2.1.1",
|
|
7
|
+
"tailwind-merge": "^3.6.0",
|
|
8
|
+
"cn": "^0.2.6",
|
|
9
|
+
"lucide-react": "^1.45.0",
|
|
10
|
+
"shadcn": "^4.21.0",
|
|
11
|
+
"tw-animate-css": "^1.4.0"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@import "tw-animate-css";
|
|
3
|
+
@import "shadcn/tailwind.css";
|
|
4
|
+
|
|
5
|
+
@custom-variant dark (&:is(.dark *));
|
|
6
|
+
|
|
7
|
+
@theme inline {
|
|
8
|
+
--color-background: var(--background);
|
|
9
|
+
--color-foreground: var(--foreground);
|
|
10
|
+
--color-card: var(--card);
|
|
11
|
+
--color-card-foreground: var(--card-foreground);
|
|
12
|
+
--color-popover: var(--popover);
|
|
13
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
14
|
+
--color-primary: var(--primary);
|
|
15
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
16
|
+
--color-secondary: var(--secondary);
|
|
17
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
18
|
+
--color-muted: var(--muted);
|
|
19
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
20
|
+
--color-accent: var(--accent);
|
|
21
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
22
|
+
--color-destructive: var(--destructive);
|
|
23
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
24
|
+
--color-border: var(--border);
|
|
25
|
+
--color-input: var(--input);
|
|
26
|
+
--color-ring: var(--ring);
|
|
27
|
+
--color-chart-1: var(--chart-1);
|
|
28
|
+
--color-chart-2: var(--chart-2);
|
|
29
|
+
--color-chart-3: var(--chart-3);
|
|
30
|
+
--color-chart-4: var(--chart-4);
|
|
31
|
+
--color-chart-5: var(--chart-5);
|
|
32
|
+
--radius-sm: calc(var(--radius) * 0.6);
|
|
33
|
+
--radius-md: calc(var(--radius) * 0.8);
|
|
34
|
+
--radius-lg: var(--radius);
|
|
35
|
+
--radius-xl: calc(var(--radius) * 1.4);
|
|
36
|
+
--radius-2xl: calc(var(--radius) * 1.8);
|
|
37
|
+
--radius-3xl: calc(var(--radius) * 2.2);
|
|
38
|
+
--radius-4xl: calc(var(--radius) * 2.6);
|
|
39
|
+
--color-sidebar: var(--sidebar);
|
|
40
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
41
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
42
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
43
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
44
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
45
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
46
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
:root {
|
|
50
|
+
--radius: 0.625rem;
|
|
51
|
+
--background: oklch(1 0 0);
|
|
52
|
+
--foreground: oklch(0.145 0 0);
|
|
53
|
+
--card: oklch(1 0 0);
|
|
54
|
+
--card-foreground: oklch(0.145 0 0);
|
|
55
|
+
--popover: oklch(1 0 0);
|
|
56
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
57
|
+
--primary: oklch(0.205 0 0);
|
|
58
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
59
|
+
--secondary: oklch(0.97 0 0);
|
|
60
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
61
|
+
--muted: oklch(0.97 0 0);
|
|
62
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
63
|
+
--accent: oklch(0.97 0 0);
|
|
64
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
65
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
66
|
+
--border: oklch(0.922 0 0);
|
|
67
|
+
--input: oklch(0.922 0 0);
|
|
68
|
+
--ring: oklch(0.708 0 0);
|
|
69
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
70
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
71
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
72
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
73
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
74
|
+
--sidebar: oklch(0.985 0 0);
|
|
75
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
76
|
+
--sidebar-primary: oklch(0.205 0 0);
|
|
77
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
78
|
+
--sidebar-accent: oklch(0.97 0 0);
|
|
79
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
80
|
+
--sidebar-border: oklch(0.922 0 0);
|
|
81
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.dark {
|
|
85
|
+
--background: oklch(0.145 0 0);
|
|
86
|
+
--foreground: oklch(0.985 0 0);
|
|
87
|
+
--card: oklch(0.205 0 0);
|
|
88
|
+
--card-foreground: oklch(0.985 0 0);
|
|
89
|
+
--popover: oklch(0.205 0 0);
|
|
90
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
91
|
+
--primary: oklch(0.922 0 0);
|
|
92
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
93
|
+
--secondary: oklch(0.269 0 0);
|
|
94
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
95
|
+
--muted: oklch(0.269 0 0);
|
|
96
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
97
|
+
--accent: oklch(0.269 0 0);
|
|
98
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
99
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
100
|
+
--border: oklch(1 0 0 / 10%);
|
|
101
|
+
--input: oklch(1 0 0 / 15%);
|
|
102
|
+
--ring: oklch(0.556 0 0);
|
|
103
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
104
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
105
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
106
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
107
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
108
|
+
--sidebar: oklch(0.205 0 0);
|
|
109
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
110
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
111
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
112
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
113
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
114
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
115
|
+
--sidebar-ring: oklch(0.556 0 0);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@layer base {
|
|
119
|
+
* {
|
|
120
|
+
@apply border-border outline-ring/50;
|
|
121
|
+
}
|
|
122
|
+
body {
|
|
123
|
+
@apply bg-background text-foreground;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { resolve } from 'path'
|
|
2
|
+
import { defineConfig } from 'electron-vite'
|
|
3
|
+
import react from '@vitejs/plugin-react'
|
|
4
|
+
import tailwindcss from '@tailwindcss/vite'
|
|
5
|
+
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
main: {},
|
|
8
|
+
preload: {},
|
|
9
|
+
renderer: {
|
|
10
|
+
resolve: {
|
|
11
|
+
alias: {
|
|
12
|
+
'@renderer': resolve('src/renderer/src')
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
plugins: [
|
|
16
|
+
react(),
|
|
17
|
+
// @ts-expect-error
|
|
18
|
+
tailwindcss()
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useAppStore'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { create } from 'zustand'
|
|
2
|
+
|
|
3
|
+
interface AppState {
|
|
4
|
+
count: number
|
|
5
|
+
increment: () => void
|
|
6
|
+
decrement: () => void
|
|
7
|
+
reset: () => void
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 应用全局状态 Store 示例
|
|
12
|
+
*/
|
|
13
|
+
export const useAppStore = create<AppState>((set) => ({
|
|
14
|
+
count: 0,
|
|
15
|
+
increment: () => set((state) => ({ count: state.count + 1 })),
|
|
16
|
+
decrement: () => set((state) => ({ count: state.count - 1 })),
|
|
17
|
+
reset: () => set({ count: 0 })
|
|
18
|
+
}))
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"name": "Debug Main Process",
|
|
6
|
+
"type": "node",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"cwd": "${workspaceRoot}",
|
|
9
|
+
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite",
|
|
10
|
+
"windows": {
|
|
11
|
+
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd"
|
|
12
|
+
},
|
|
13
|
+
"runtimeArgs": ["--sourcemap"],
|
|
14
|
+
"env": {
|
|
15
|
+
"REMOTE_DEBUGGING_PORT": "9222"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "Debug Renderer Process",
|
|
20
|
+
"port": 9222,
|
|
21
|
+
"request": "attach",
|
|
22
|
+
"type": "chrome",
|
|
23
|
+
"webRoot": "${workspaceFolder}/src/renderer",
|
|
24
|
+
"timeout": 60000,
|
|
25
|
+
"presentation": {
|
|
26
|
+
"hidden": true
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"compounds": [
|
|
31
|
+
{
|
|
32
|
+
"name": "Debug All",
|
|
33
|
+
"configurations": ["Debug Main Process", "Debug Renderer Process"],
|
|
34
|
+
"presentation": {
|
|
35
|
+
"order": 1
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# electron-vite-react
|
|
2
|
+
|
|
3
|
+
An Electron application with React and TypeScript
|
|
4
|
+
|
|
5
|
+
## Recommended IDE Setup
|
|
6
|
+
|
|
7
|
+
- [VSCode](https://code.visualstudio.com/) + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) + [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
|
|
8
|
+
|
|
9
|
+
## Project Setup
|
|
10
|
+
|
|
11
|
+
### Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
$ pnpm install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Development
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
$ pnpm dev
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Build
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# For windows
|
|
27
|
+
$ pnpm build:win
|
|
28
|
+
|
|
29
|
+
# For macOS
|
|
30
|
+
$ pnpm build:mac
|
|
31
|
+
|
|
32
|
+
# For Linux
|
|
33
|
+
$ pnpm build:linux
|
|
34
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>com.apple.security.cs.allow-jit</key>
|
|
6
|
+
<true/>
|
|
7
|
+
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
|
8
|
+
<true/>
|
|
9
|
+
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
|
10
|
+
<true/>
|
|
11
|
+
</dict>
|
|
12
|
+
</plist>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
appId: com.electron.app
|
|
2
|
+
productName: electron-vite-react
|
|
3
|
+
directories:
|
|
4
|
+
buildResources: build
|
|
5
|
+
files:
|
|
6
|
+
- '!**/.vscode/*'
|
|
7
|
+
- '!src/*'
|
|
8
|
+
- '!electron.vite.config.{js,ts,mjs,cjs}'
|
|
9
|
+
- '!{.eslintcache,eslint.config.mjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
|
|
10
|
+
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
|
|
11
|
+
- '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}'
|
|
12
|
+
asarUnpack:
|
|
13
|
+
- resources/**
|
|
14
|
+
win:
|
|
15
|
+
executableName: electron-vite-react
|
|
16
|
+
nsis:
|
|
17
|
+
artifactName: ${name}-${version}-setup.${ext}
|
|
18
|
+
shortcutName: ${productName}
|
|
19
|
+
uninstallDisplayName: ${productName}
|
|
20
|
+
createDesktopShortcut: always
|
|
21
|
+
mac:
|
|
22
|
+
entitlementsInherit: build/entitlements.mac.plist
|
|
23
|
+
extendInfo:
|
|
24
|
+
- NSCameraUsageDescription: Application requests access to the device's camera.
|
|
25
|
+
- NSMicrophoneUsageDescription: Application requests access to the device's microphone.
|
|
26
|
+
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder.
|
|
27
|
+
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
|
|
28
|
+
notarize: false
|
|
29
|
+
dmg:
|
|
30
|
+
artifactName: ${name}-${version}.${ext}
|
|
31
|
+
linux:
|
|
32
|
+
target:
|
|
33
|
+
- AppImage
|
|
34
|
+
- snap
|
|
35
|
+
- deb
|
|
36
|
+
maintainer: electronjs.org
|
|
37
|
+
category: Utility
|
|
38
|
+
appImage:
|
|
39
|
+
artifactName: ${name}-${version}.${ext}
|
|
40
|
+
npmRebuild: false
|
|
41
|
+
publish:
|
|
42
|
+
provider: generic
|
|
43
|
+
url: https://example.com/auto-updates
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { resolve } from 'path'
|
|
2
|
+
import { defineConfig } from 'electron-vite'
|
|
3
|
+
import react from '@vitejs/plugin-react'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
main: {},
|
|
7
|
+
preload: {},
|
|
8
|
+
renderer: {
|
|
9
|
+
resolve: {
|
|
10
|
+
alias: {
|
|
11
|
+
'@renderer': resolve('src/renderer/src')
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
plugins: [react()]
|
|
15
|
+
}
|
|
16
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { defineConfig } from 'eslint/config'
|
|
2
|
+
import tseslint from '@electron-toolkit/eslint-config-ts'
|
|
3
|
+
import eslintConfigPrettier from '@electron-toolkit/eslint-config-prettier'
|
|
4
|
+
import eslintPluginReact from 'eslint-plugin-react'
|
|
5
|
+
import eslintPluginReactHooks from 'eslint-plugin-react-hooks'
|
|
6
|
+
import eslintPluginReactRefresh from 'eslint-plugin-react-refresh'
|
|
7
|
+
|
|
8
|
+
export default defineConfig(
|
|
9
|
+
{ ignores: ['**/node_modules', '**/dist', '**/out'] },
|
|
10
|
+
tseslint.configs.recommended,
|
|
11
|
+
eslintPluginReact.configs.flat.recommended,
|
|
12
|
+
eslintPluginReact.configs.flat['jsx-runtime'],
|
|
13
|
+
{
|
|
14
|
+
settings: {
|
|
15
|
+
react: {
|
|
16
|
+
version: 'detect'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
files: ['**/*.{ts,tsx}'],
|
|
22
|
+
plugins: {
|
|
23
|
+
'react-hooks': eslintPluginReactHooks,
|
|
24
|
+
'react-refresh': eslintPluginReactRefresh
|
|
25
|
+
},
|
|
26
|
+
rules: {
|
|
27
|
+
...eslintPluginReactHooks.configs.recommended.rules,
|
|
28
|
+
...eslintPluginReactRefresh.configs.vite.rules
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
eslintConfigPrettier
|
|
32
|
+
)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "electron-vite-react",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "An Electron application with React and TypeScript",
|
|
5
|
+
"main": "./out/main/index.js",
|
|
6
|
+
"author": "example.com",
|
|
7
|
+
"homepage": "https://electron-vite.org",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"format": "prettier --write .",
|
|
10
|
+
"lint": "eslint --cache .",
|
|
11
|
+
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
|
|
12
|
+
"typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false",
|
|
13
|
+
"typecheck": "npm run typecheck:node && npm run typecheck:web",
|
|
14
|
+
"start": "electron-vite preview",
|
|
15
|
+
"dev": "electron-vite dev",
|
|
16
|
+
"build": "npm run typecheck && electron-vite build",
|
|
17
|
+
"postinstall": "electron-builder install-app-deps",
|
|
18
|
+
"build:unpack": "npm run build && electron-builder --dir",
|
|
19
|
+
"build:win": "npm run build && electron-builder --win",
|
|
20
|
+
"build:mac": "electron-vite build && electron-builder --mac",
|
|
21
|
+
"build:linux": "electron-vite build && electron-builder --linux"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@electron-toolkit/preload": "^3.0.2",
|
|
25
|
+
"@electron-toolkit/utils": "^4.0.0",
|
|
26
|
+
"electron-updater": "^6.3.9"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@electron-toolkit/eslint-config-prettier": "^3.0.0",
|
|
30
|
+
"@electron-toolkit/eslint-config-ts": "^3.1.0",
|
|
31
|
+
"@electron-toolkit/tsconfig": "^2.0.0",
|
|
32
|
+
"@types/node": "^22.19.1",
|
|
33
|
+
"@types/react": "^19.2.7",
|
|
34
|
+
"@types/react-dom": "^19.2.3",
|
|
35
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
36
|
+
"electron": "^39.2.6",
|
|
37
|
+
"electron-builder": "^26.0.12",
|
|
38
|
+
"electron-vite": "^5.0.0",
|
|
39
|
+
"eslint": "^9.39.1",
|
|
40
|
+
"eslint-plugin-react": "^7.37.5",
|
|
41
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
42
|
+
"eslint-plugin-react-refresh": "^0.4.24",
|
|
43
|
+
"prettier": "^3.7.4",
|
|
44
|
+
"react": "^19.2.1",
|
|
45
|
+
"react-dom": "^19.2.1",
|
|
46
|
+
"typescript": "^5.9.3",
|
|
47
|
+
"vite": "^7.2.6"
|
|
48
|
+
},
|
|
49
|
+
"pnpm": {
|
|
50
|
+
"onlyBuiltDependencies": [
|
|
51
|
+
"electron",
|
|
52
|
+
"esbuild",
|
|
53
|
+
"electron-winstaller"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { app, shell, BrowserWindow, ipcMain } from 'electron'
|
|
2
|
+
import { join } from 'path'
|
|
3
|
+
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
|
4
|
+
import icon from '../../resources/icon.png?asset'
|
|
5
|
+
|
|
6
|
+
function createWindow(): void {
|
|
7
|
+
// Create the browser window.
|
|
8
|
+
const mainWindow = new BrowserWindow({
|
|
9
|
+
width: 900,
|
|
10
|
+
height: 670,
|
|
11
|
+
show: false,
|
|
12
|
+
autoHideMenuBar: true,
|
|
13
|
+
...(process.platform === 'linux' ? { icon } : {}),
|
|
14
|
+
webPreferences: {
|
|
15
|
+
preload: join(__dirname, '../preload/index.js'),
|
|
16
|
+
sandbox: false
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
mainWindow.on('ready-to-show', () => {
|
|
21
|
+
mainWindow.show()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
mainWindow.webContents.setWindowOpenHandler((details) => {
|
|
25
|
+
shell.openExternal(details.url)
|
|
26
|
+
return { action: 'deny' }
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
// HMR for renderer base on electron-vite cli.
|
|
30
|
+
// Load the remote URL for development or the local html file for production.
|
|
31
|
+
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
|
32
|
+
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
|
|
33
|
+
} else {
|
|
34
|
+
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// This method will be called when Electron has finished
|
|
39
|
+
// initialization and is ready to create browser windows.
|
|
40
|
+
// Some APIs can only be used after this event occurs.
|
|
41
|
+
app.whenReady().then(() => {
|
|
42
|
+
// Set app user model id for windows
|
|
43
|
+
electronApp.setAppUserModelId('com.electron')
|
|
44
|
+
|
|
45
|
+
// Default open or close DevTools by F12 in development
|
|
46
|
+
// and ignore CommandOrControl + R in production.
|
|
47
|
+
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
|
48
|
+
app.on('browser-window-created', (_, window) => {
|
|
49
|
+
optimizer.watchWindowShortcuts(window)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
createWindow()
|
|
53
|
+
|
|
54
|
+
app.on('activate', function () {
|
|
55
|
+
// On macOS it's common to re-create a window in the app when the
|
|
56
|
+
// dock icon is clicked and there are no other windows open.
|
|
57
|
+
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
// Quit when all windows are closed, except on macOS. There, it's common
|
|
62
|
+
// for applications and their menu bar to stay active until the user quits
|
|
63
|
+
// explicitly with Cmd + Q.
|
|
64
|
+
app.on('window-all-closed', () => {
|
|
65
|
+
if (process.platform !== 'darwin') {
|
|
66
|
+
app.quit()
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
// In this file you can include the rest of your app's specific main process
|
|
71
|
+
// code. You can also put them in separate files and require them here.
|
|
72
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { contextBridge } from 'electron'
|
|
2
|
+
import { electronAPI } from '@electron-toolkit/preload'
|
|
3
|
+
|
|
4
|
+
// Custom APIs for renderer
|
|
5
|
+
const api = {}
|
|
6
|
+
|
|
7
|
+
// Use `contextBridge` APIs to expose Electron APIs to
|
|
8
|
+
// renderer only if context isolation is enabled, otherwise
|
|
9
|
+
// just add to the DOM global.
|
|
10
|
+
if (process.contextIsolated) {
|
|
11
|
+
try {
|
|
12
|
+
contextBridge.exposeInMainWorld('electron', electronAPI)
|
|
13
|
+
contextBridge.exposeInMainWorld('api', api)
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error(error)
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
// @ts-ignore (define in dts)
|
|
19
|
+
window.electron = electronAPI
|
|
20
|
+
// @ts-ignore (define in dts)
|
|
21
|
+
window.api = api
|
|
22
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>Electron</title>
|
|
6
|
+
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
|
7
|
+
<meta
|
|
8
|
+
http-equiv="Content-Security-Policy"
|
|
9
|
+
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
|
|
10
|
+
/>
|
|
11
|
+
</head>
|
|
12
|
+
|
|
13
|
+
<body>
|
|
14
|
+
<div id="root"></div>
|
|
15
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@electron-toolkit/tsconfig/tsconfig.web.json",
|
|
3
|
+
"include": [
|
|
4
|
+
"src/renderer/src/env.d.ts",
|
|
5
|
+
"src/renderer/src/**/*",
|
|
6
|
+
"src/renderer/src/**/*.tsx",
|
|
7
|
+
"src/preload/*.d.ts"
|
|
8
|
+
],
|
|
9
|
+
"compilerOptions": {
|
|
10
|
+
"composite": true,
|
|
11
|
+
"jsx": "react-jsx",
|
|
12
|
+
"baseUrl": ".",
|
|
13
|
+
"paths": {
|
|
14
|
+
"@renderer/*": [
|
|
15
|
+
"src/renderer/src/*"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|