@stevederico/skateboard-ui 1.1.4 → 1.2.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/CHANGELOG.md +5 -0
- package/Utilities.js +1 -0
- package/ViteConfig.js +276 -0
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
package/Utilities.js
CHANGED
package/ViteConfig.js
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite configuration utilities for skateboard-ui
|
|
3
|
+
* This file is for build-time use only (in vite.config.js)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Custom logger plugin for Vite
|
|
8
|
+
*/
|
|
9
|
+
export const customLoggerPlugin = () => {
|
|
10
|
+
return {
|
|
11
|
+
name: 'custom-logger',
|
|
12
|
+
configureServer(server) {
|
|
13
|
+
server.printUrls = () => {
|
|
14
|
+
console.log(`🖥️ React is running on http://localhost:${server.config.server.port || 5173}`);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* HTML replacement plugin
|
|
22
|
+
* Replaces {{APP_NAME}}, {{TAGLINE}}, {{COMPANY_WEBSITE}} in index.html
|
|
23
|
+
*/
|
|
24
|
+
export const htmlReplacePlugin = () => {
|
|
25
|
+
return {
|
|
26
|
+
name: 'html-replace',
|
|
27
|
+
async transformIndexHtml(html) {
|
|
28
|
+
const { readFileSync } = await import('node:fs');
|
|
29
|
+
const constants = JSON.parse(readFileSync('src/constants.json', 'utf8'));
|
|
30
|
+
|
|
31
|
+
return html
|
|
32
|
+
.replace(/{{APP_NAME}}/g, constants.appName)
|
|
33
|
+
.replace(/{{TAGLINE}}/g, constants.tagline)
|
|
34
|
+
.replace(/{{COMPANY_WEBSITE}}/g, constants.companyWebsite);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Dynamic robots.txt plugin
|
|
41
|
+
*/
|
|
42
|
+
export const dynamicRobotsPlugin = () => {
|
|
43
|
+
return {
|
|
44
|
+
name: 'dynamic-robots',
|
|
45
|
+
async generateBundle() {
|
|
46
|
+
const { readFileSync } = await import('node:fs');
|
|
47
|
+
const constants = JSON.parse(readFileSync('src/constants.json', 'utf8'));
|
|
48
|
+
const website = constants.companyWebsite.startsWith('http')
|
|
49
|
+
? constants.companyWebsite
|
|
50
|
+
: `https://${constants.companyWebsite}`;
|
|
51
|
+
|
|
52
|
+
const robotsContent = `User-agent: Googlebot
|
|
53
|
+
Disallow: /app/
|
|
54
|
+
Disallow: /console/
|
|
55
|
+
Disallow: /signin/
|
|
56
|
+
Disallow: /signup/
|
|
57
|
+
|
|
58
|
+
User-agent: Bingbot
|
|
59
|
+
Disallow: /app/
|
|
60
|
+
Disallow: /console/
|
|
61
|
+
Disallow: /signin/
|
|
62
|
+
Disallow: /signup/
|
|
63
|
+
|
|
64
|
+
User-agent: Applebot
|
|
65
|
+
Disallow: /app/
|
|
66
|
+
Disallow: /console/
|
|
67
|
+
Disallow: /signin/
|
|
68
|
+
Disallow: /signup/
|
|
69
|
+
|
|
70
|
+
User-agent: facebookexternalhit
|
|
71
|
+
Disallow: /app/
|
|
72
|
+
Disallow: /console/
|
|
73
|
+
Disallow: /signin/
|
|
74
|
+
Disallow: /signup/
|
|
75
|
+
|
|
76
|
+
User-agent: Twitterbot
|
|
77
|
+
Allow: /
|
|
78
|
+
|
|
79
|
+
User-agent: LinkedInBot
|
|
80
|
+
Allow: /
|
|
81
|
+
|
|
82
|
+
User-agent: WhatsApp
|
|
83
|
+
Allow: /
|
|
84
|
+
|
|
85
|
+
User-agent: *
|
|
86
|
+
Disallow: /app/
|
|
87
|
+
Disallow: /console/
|
|
88
|
+
Disallow: /signin/
|
|
89
|
+
Disallow: /signup/
|
|
90
|
+
Allow: /
|
|
91
|
+
|
|
92
|
+
Sitemap: ${website}/sitemap.xml`;
|
|
93
|
+
|
|
94
|
+
this.emitFile({
|
|
95
|
+
type: 'asset',
|
|
96
|
+
fileName: 'robots.txt',
|
|
97
|
+
source: robotsContent
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Dynamic sitemap.xml plugin
|
|
105
|
+
*/
|
|
106
|
+
export const dynamicSitemapPlugin = () => {
|
|
107
|
+
return {
|
|
108
|
+
name: 'dynamic-sitemap',
|
|
109
|
+
async generateBundle() {
|
|
110
|
+
const { readFileSync } = await import('node:fs');
|
|
111
|
+
const constants = JSON.parse(readFileSync('src/constants.json', 'utf8'));
|
|
112
|
+
const website = constants.companyWebsite.startsWith('http')
|
|
113
|
+
? constants.companyWebsite
|
|
114
|
+
: `https://${constants.companyWebsite}`;
|
|
115
|
+
|
|
116
|
+
const currentDate = new Date().toISOString().split('T')[0];
|
|
117
|
+
|
|
118
|
+
const sitemapContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
119
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
120
|
+
<url>
|
|
121
|
+
<loc>${website}/</loc>
|
|
122
|
+
<lastmod>${currentDate}</lastmod>
|
|
123
|
+
<changefreq>weekly</changefreq>
|
|
124
|
+
<priority>1.0</priority>
|
|
125
|
+
</url>
|
|
126
|
+
<url>
|
|
127
|
+
<loc>${website}/terms</loc>
|
|
128
|
+
<lastmod>${currentDate}</lastmod>
|
|
129
|
+
<changefreq>monthly</changefreq>
|
|
130
|
+
<priority>0.8</priority>
|
|
131
|
+
</url>
|
|
132
|
+
<url>
|
|
133
|
+
<loc>${website}/privacy</loc>
|
|
134
|
+
<lastmod>${currentDate}</lastmod>
|
|
135
|
+
<changefreq>monthly</changefreq>
|
|
136
|
+
<priority>0.8</priority>
|
|
137
|
+
</url>
|
|
138
|
+
<url>
|
|
139
|
+
<loc>${website}/signin</loc>
|
|
140
|
+
<lastmod>${currentDate}</lastmod>
|
|
141
|
+
<changefreq>weekly</changefreq>
|
|
142
|
+
<priority>0.6</priority>
|
|
143
|
+
</url>
|
|
144
|
+
<url>
|
|
145
|
+
<loc>${website}/signup</loc>
|
|
146
|
+
<lastmod>${currentDate}</lastmod>
|
|
147
|
+
<changefreq>weekly</changefreq>
|
|
148
|
+
<priority>0.6</priority>
|
|
149
|
+
</url>
|
|
150
|
+
</urlset>`;
|
|
151
|
+
|
|
152
|
+
this.emitFile({
|
|
153
|
+
type: 'asset',
|
|
154
|
+
fileName: 'sitemap.xml',
|
|
155
|
+
source: sitemapContent
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Dynamic manifest.json plugin
|
|
163
|
+
*/
|
|
164
|
+
export const dynamicManifestPlugin = () => {
|
|
165
|
+
return {
|
|
166
|
+
name: 'dynamic-manifest',
|
|
167
|
+
async generateBundle() {
|
|
168
|
+
const { readFileSync } = await import('node:fs');
|
|
169
|
+
const constants = JSON.parse(readFileSync('src/constants.json', 'utf8'));
|
|
170
|
+
|
|
171
|
+
const manifestContent = {
|
|
172
|
+
short_name: constants.appName,
|
|
173
|
+
name: constants.appName,
|
|
174
|
+
description: constants.tagline,
|
|
175
|
+
icons: [
|
|
176
|
+
{
|
|
177
|
+
src: "/icons/icon.svg",
|
|
178
|
+
sizes: "192x192",
|
|
179
|
+
type: "image/svg+xml"
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
start_url: "./app",
|
|
183
|
+
display: "standalone",
|
|
184
|
+
theme_color: "#000000",
|
|
185
|
+
background_color: "#ffffff"
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
this.emitFile({
|
|
189
|
+
type: 'asset',
|
|
190
|
+
fileName: 'manifest.json',
|
|
191
|
+
source: JSON.stringify(manifestContent, null, 2)
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Complete Vite config generator
|
|
199
|
+
* Returns standard skateboard config with optional overrides
|
|
200
|
+
*/
|
|
201
|
+
export async function getSkateboardViteConfig(customConfig = {}) {
|
|
202
|
+
const [react, tailwindcss, { resolve }, path] = await Promise.all([
|
|
203
|
+
import('@vitejs/plugin-react-swc').then(m => m.default),
|
|
204
|
+
import('@tailwindcss/vite').then(m => m.default),
|
|
205
|
+
import('node:path'),
|
|
206
|
+
import('node:path')
|
|
207
|
+
]);
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
plugins: [
|
|
211
|
+
react(),
|
|
212
|
+
tailwindcss(),
|
|
213
|
+
customLoggerPlugin(),
|
|
214
|
+
htmlReplacePlugin(),
|
|
215
|
+
dynamicRobotsPlugin(),
|
|
216
|
+
dynamicSitemapPlugin(),
|
|
217
|
+
dynamicManifestPlugin(),
|
|
218
|
+
...(customConfig.plugins || [])
|
|
219
|
+
],
|
|
220
|
+
esbuild: {
|
|
221
|
+
drop: []
|
|
222
|
+
},
|
|
223
|
+
resolve: {
|
|
224
|
+
alias: {
|
|
225
|
+
'@': resolve(process.cwd(), './src'),
|
|
226
|
+
'@package': path.resolve(process.cwd(), 'package.json'),
|
|
227
|
+
'@root': path.resolve(process.cwd()),
|
|
228
|
+
'react/jsx-runtime': path.resolve(process.cwd(), 'node_modules/react/jsx-runtime.js'),
|
|
229
|
+
...(customConfig.resolve?.alias || {})
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
optimizeDeps: {
|
|
233
|
+
include: [
|
|
234
|
+
'react',
|
|
235
|
+
'react-dom',
|
|
236
|
+
'react-dom/client',
|
|
237
|
+
'@radix-ui/react-slot',
|
|
238
|
+
...(customConfig.optimizeDeps?.include || [])
|
|
239
|
+
],
|
|
240
|
+
exclude: [
|
|
241
|
+
'@swc/core',
|
|
242
|
+
'@swc/core-darwin-arm64',
|
|
243
|
+
'@swc/wasm',
|
|
244
|
+
'lightningcss',
|
|
245
|
+
'fsevents',
|
|
246
|
+
'cookie',
|
|
247
|
+
'set-cookie-parser',
|
|
248
|
+
...(customConfig.optimizeDeps?.exclude || [])
|
|
249
|
+
],
|
|
250
|
+
esbuildOptions: {
|
|
251
|
+
target: 'esnext',
|
|
252
|
+
define: {
|
|
253
|
+
global: 'globalThis'
|
|
254
|
+
},
|
|
255
|
+
...(customConfig.optimizeDeps?.esbuildOptions || {})
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
server: {
|
|
259
|
+
host: 'localhost',
|
|
260
|
+
open: false,
|
|
261
|
+
port: 5173,
|
|
262
|
+
strictPort: false,
|
|
263
|
+
hmr: {
|
|
264
|
+
port: 5173,
|
|
265
|
+
overlay: false,
|
|
266
|
+
},
|
|
267
|
+
watch: {
|
|
268
|
+
usePolling: false,
|
|
269
|
+
ignored: ['**/node_modules/**', '**/.git/**']
|
|
270
|
+
},
|
|
271
|
+
...(customConfig.server || {})
|
|
272
|
+
},
|
|
273
|
+
logLevel: 'error',
|
|
274
|
+
...customConfig
|
|
275
|
+
};
|
|
276
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stevederico/skateboard-ui",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./AppSidebar": {
|
|
@@ -76,6 +76,10 @@
|
|
|
76
76
|
"import": "./Utilities.js",
|
|
77
77
|
"default": "./Utilities.js"
|
|
78
78
|
},
|
|
79
|
+
"./ViteConfig": {
|
|
80
|
+
"import": "./ViteConfig.js",
|
|
81
|
+
"default": "./ViteConfig.js"
|
|
82
|
+
},
|
|
79
83
|
"./ProtectedRoute": {
|
|
80
84
|
"import": "./ProtectedRoute.jsx",
|
|
81
85
|
"default": "./ProtectedRoute.jsx"
|