vaderjs 1.4.2-jpiml56 → 1.4.2-kml56

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.
@@ -1 +1,235 @@
1
- export class Kuai{constructor(t={container:"#app"}){this.routes=[],this.middleware=[],this.container=t.container?t.container:document.getElementById("app"),this.renderPlugins=[]}res={text:t=>{this.container.innerHTML=t},html:t=>{switch(typeof t){case"function":if(this.renderPlugins.length>0)return void this.renderPlugins.forEach((e=>{"html"===e.for&&(console.log("Plugin",e),e.plugin(t,this.container))}));this.container.innerHTML=t();break;case"string":this.container.innerHTML=t}},json:t=>{this.container.innerHTML=`<Oject data=${JSON.stringify(t)}></Object>`}};req={navigate:t=>{window.history.pushState({},"",t);let e=this.match(window.location.pathname.replace("/index.html",""));e&&(this.currentRoute=e.path,e.callback(this.res,e.params,this.extractQueryParams(window.location.search)))},back:()=>{window.history.back()},forward:()=>{window.history.forward()},url:window.location};extractQueryParams(t){let e=new URLSearchParams(t),i={};for(let t of e)i[t[0]]=t[1];return i}extractParams(t,e){const i=t.split("/").filter((t=>""!==t)),r=e.split("/").filter((t=>""!==t)),a={};return i.forEach(((t,e)=>{if(t.startsWith(":")){const i=t.slice(1);a[i]=r[e]}else if(t.startsWith("*")){r.slice(e).forEach(((t,e)=>{a[e]=t}))}})),a}use(t,e){this.middleware.push({path:t,middleware:e})}usePlugin(t,e){this.renderPlugins.push({plugin:t,for:e})}match(t){(t=t.endsWith("/")?t.slice(0,-1):t).includes("index.html")&&(t=t.replace("index.html","")),t.includes("?")&&(t=t.split("?")[0]);let e=this.routes.find((e=>{if(e.path===t)return!0;if(""===t&&"/"===e.path)return!0;if(e.path.includes("*")||e.path.includes(":")){const i=e.path.split("/").filter((t=>""!==t)),r=t.split("/").filter((t=>""!==t));if(this.basePath&&r.shift(),i.length!==r.length&&!e.path.endsWith("*"))return!1;for(let t=0;t<i.length;t++){const e=i[t],a=r[t];if(!e.startsWith(":")&&!e.startsWith("*")&&e!==a)return!1}return!0}}));if(e){let i=this.extractParams(e.path,t);return{...e,params:i}}return null}get(t,e){this.routes.push({path:t,callback:e})}listen(){let t=this.match(window.location.pathname.replace("/index.html",""));if(t){this.middleware.forEach((e=>{e.path===t.path&&e.middleware()})),this.currentRoute=t.path;let e={...this.res,res:this.res,req:{...this.req,params:e=>t.params[e]}};t.callback(e)}window.onpopstate=()=>{let t=this.match(window.location.pathname.replace("/index.html",""));t&&(this.currentRoute=t.path,t.callback(this.res,t.params,this.extractQueryParams(window.location.search)))}}}export default Kuai;
1
+ /**
2
+ * @fileoverview - A simple router for vaderjs - Kuai
3
+ * @version - 1.0.0
4
+ */
5
+ export class Kuai{
6
+ constructor(config = { container: '#app'}){
7
+ this.routes = [];
8
+ this.middleware = [];
9
+ this.container = config.container ? config.container : document.getElementById('app');
10
+ this.renderPlugins = [];
11
+ }
12
+
13
+ res = {
14
+ /**
15
+ * @description render text to the container
16
+ * @param {string} data
17
+ */
18
+ text: (data) => {
19
+ this.container.innerHTML = data;
20
+ },
21
+ /**
22
+ * @method html
23
+ * @description render html to the container
24
+ * @param {any} data
25
+ * @returns
26
+ */
27
+ html: (data) => {
28
+ switch(typeof data){
29
+ case 'function':
30
+ if(this.renderPlugins.length > 0){
31
+ this.renderPlugins.forEach((plugin) => {
32
+ if(plugin.for === 'html'){
33
+ console.log('Plugin', plugin)
34
+ plugin.plugin(data, this.container)
35
+ }
36
+ })
37
+ return;
38
+ }
39
+ this.container.innerHTML = data();
40
+ break;
41
+ case 'string':
42
+ this.container.innerHTML = data;
43
+ break;
44
+ }
45
+
46
+ },
47
+ /**
48
+ * @method json
49
+ * @description render json to the container
50
+ * @param {Object} data
51
+ */
52
+ json: (data) => {
53
+ this.container.innerHTML = `<Oject data=${JSON.stringify(data)}></Object>`
54
+ }
55
+ }
56
+ req = {
57
+ /**
58
+ * @method navigate
59
+ * @description - navigate to a new route
60
+ * @param {string} path
61
+ */
62
+ navigate: (path) => {
63
+ window.history.pushState({}, '', path);
64
+ let currentPath = this.match(window.location.pathname.replace('/index.html', ''))
65
+ if(currentPath){
66
+ this.currentRoute = currentPath.path
67
+ currentPath.callback(this.res, currentPath.params, this.extractQueryParams(window.location.search));
68
+ }
69
+ },
70
+ /**
71
+ * @method back
72
+ * @description - go back to the previous route
73
+ */
74
+ back: () => {
75
+ window.history.back();
76
+ },
77
+
78
+ /**
79
+ * @method forward
80
+ * @description - go forward to the next route
81
+ * @returns {void}
82
+ * **/
83
+ forward: () => {
84
+ window.history.forward();
85
+ },
86
+ url: window.location
87
+ }
88
+ /**
89
+ * @private
90
+ */
91
+ extractQueryParams(path){
92
+ let params = new URLSearchParams(path);
93
+ let query = {};
94
+ for(let param of params){
95
+ query[param[0]] = param[1];
96
+ }
97
+ return query;
98
+ }
99
+ /**
100
+ * @private
101
+ */
102
+ extractParams(routePath, currentPath){
103
+ const routeParts = routePath.split('/').filter((part) => part !== '');
104
+ const hashParts = currentPath.split('/').filter((part) => part !== '');
105
+ const params = {};
106
+ routeParts.forEach((part, index) => {
107
+ if (part.startsWith(':')) {
108
+ const paramName = part.slice(1);
109
+ params[paramName] = hashParts[index];
110
+ }else if(part.startsWith('*')){
111
+ let array = hashParts.slice(index)
112
+ array.forEach((i, index)=>{
113
+ params[index] = i
114
+ })
115
+ };
116
+ });
117
+ return params;
118
+ }
119
+ use(path, middleware){
120
+ this.middleware.push({path, middleware});
121
+ }
122
+ /**
123
+ * @method usePlugin
124
+ * @description - add a plugin to handle how the route should be rendered
125
+ * @param {Function} plugin
126
+ * @param {('html')} method
127
+ */
128
+ usePlugin(plugin, method){
129
+ this.renderPlugins.push({plugin, for: method})
130
+ }
131
+ /**
132
+ * @method match
133
+ * @description - match a route to the current path and return the route object
134
+ * @param {string} route
135
+ * @returns {Object} - {path: string, callback: Function, params: Object}
136
+ */
137
+ match(hash){
138
+ hash = hash.endsWith('/') ? hash.slice(0, -1) : hash;
139
+ hash.includes('index.html') ? hash = hash.replace('index.html', '') : null;
140
+ if(hash.includes('?')){
141
+ hash = hash.split('?')[0]
142
+ }
143
+ let route = this.routes.find((route) => {
144
+ if (route.path === hash) {
145
+ return true;
146
+ }
147
+
148
+ if(hash === '' && route.path === '/'){
149
+ return true
150
+ }
151
+
152
+
153
+ if (route.path.includes('*') || route.path.includes(':')) {
154
+ const routeParts = route.path.split('/').filter((part) => part !== '');
155
+ const hashParts = hash.split('/').filter((part) => part !== '');
156
+ if(this.basePath){
157
+ hashParts.shift();
158
+ }
159
+ if (routeParts.length !== hashParts.length && !route.path.endsWith('*')) {
160
+ return false;
161
+ }
162
+
163
+ for (let index = 0; index < routeParts.length; index++) {
164
+ const routePart = routeParts[index];
165
+ const hashPart = hashParts[index];
166
+
167
+
168
+ if (routePart.startsWith(':') || routePart.startsWith('*')) {
169
+
170
+ continue;
171
+ }
172
+
173
+ if (routePart !== hashPart) {
174
+ return false;
175
+ }
176
+ }
177
+
178
+
179
+ return true;
180
+ }
181
+
182
+ });
183
+ if(route){
184
+ let params = this.extractParams(route.path, hash)
185
+ return { ...route, params}
186
+ }
187
+ return null;
188
+
189
+ }
190
+
191
+ /**
192
+ * @description - create a new route
193
+ * @param {string} path
194
+ * @param {Function} callback
195
+ */
196
+ get(path, callback){
197
+ this.routes.push({path, callback});
198
+ }
199
+
200
+ /**
201
+ * @method listen
202
+ * @description - listen for route changes
203
+ */
204
+ listen(){
205
+ let currentPath = this.match(window.location.pathname.replace('/index.html', ''))
206
+ if(currentPath){
207
+ this.middleware.forEach((middleware) => {
208
+ if(middleware.path === currentPath.path){
209
+ middleware.middleware();
210
+ }
211
+ });
212
+ this.currentRoute = currentPath.path
213
+ let obj = {
214
+ ...this.res,
215
+ res: this.res,
216
+ req:{
217
+ ...this.req,
218
+ params: (param) => currentPath.params[param]
219
+
220
+ }
221
+ }
222
+ currentPath.callback(obj);
223
+ }
224
+ window.onpopstate = () => {
225
+ let currentPath = this.match(window.location.pathname.replace('/index.html', ''))
226
+ if(currentPath){
227
+ this.currentRoute = currentPath.path
228
+ currentPath.callback(this.res, currentPath.params, this.extractQueryParams(window.location.search));
229
+ }
230
+ }
231
+
232
+ }
233
+ }
234
+
235
+ export default Kuai;
@@ -1,5 +1,5 @@
1
1
  import * as Bun from 'bun'
2
- import { Document, DOMParser} from 'vaderjs/binaries/Kalix/index.js'
2
+ import { Element, Document, DOMParser} from 'vaderjs/binaries/Kalix/index.js'
3
3
  import { renderToString } from '../../server'
4
4
  import fs from 'fs'
5
5
  let routes = new Bun.FileSystemRouter({
@@ -11,77 +11,35 @@ async function generate(){
11
11
  let config = await import(process.cwd() + '/vader.config.js').then((config) => { return config.default })
12
12
  let provider = config?.host?.provider
13
13
 
14
- let providerRoutes = []
15
- Object.keys(routes).map((route) => {
16
- if(route.includes('[')){
17
-
18
- let root = Object.keys(routes).find((r) => {
19
- return r === '/'
20
- } )
21
-
22
-
23
- let param = route.split('/[')[1].split(']')[0]
24
- let p = {}
25
- let existingParams = routes[root]?.params || []
26
- existingParams.push({
27
- isCatchAll: route.includes('[[catchall]]') ? true : false,
28
- name: param,
29
- file: routes[route],
30
- baseFolder: route.split('[')[0]
31
- })
32
- p.file = routes[root]
33
- p.params = existingParams
34
- routes[root] = p
35
- delete routes[route]
36
-
37
- }
38
- })
14
+ let providerRoutes = []
39
15
  for(var i in routes){
40
- let path = i
16
+ let path = i
41
17
  let file = routes[i]
42
- if(typeof file === 'object'){
43
- file = file.file
44
- }
45
- let comp = require(file).default
46
- if(!comp){
47
- continue;
48
- }
49
-
50
- let dom = await renderToString(comp)
51
- let isHtml = dom.includes('<html')
18
+ let comp = require(file).default
19
+ let document = new Document()
20
+ let div = document.createElement('div')
21
+ div.setAttribute('id', 'root')
22
+ let dom = await renderToString(comp)
23
+ div.setContent(dom)
24
+ dom = div.toString("outerHTML")
52
25
  let folder = path.split('/pages')[0]
53
26
  let newPath = process.cwd() + '/build' + folder + '/index.html'
54
- let name = comp.name || 'App'
27
+ let name = comp.name
55
28
  file = file.replace(/\\/g, '/').replace('\/\/', '/').replace(process.cwd().replace(/\\/g, '/'), '').split('/pages')[1].replace('.tsx', '.js').replace('.jsx', '.js')
56
- let isParamRoute = routes[i].params ? true : false
29
+ let isParamRoute = path.includes('[')
57
30
  let baseFolder = ''
58
31
  if(isParamRoute){
59
- let route = routes[i].params[0]
60
- baseFolder = i.split('[')[0]
32
+ baseFolder = path.split('[')[0]
61
33
  let providerPath;
62
34
  switch(true){
63
35
  case provider === 'vercel':
64
- if(route.isCatchAll){
65
- providerPath = `${baseFolder}/*`
66
- providerRoutes.push({source: providerPath, destination: `${path}/index.html`})
67
- break;
68
- }
69
- providerPath = `${baseFolder}:${route.name}`
70
- providerRoutes.push({source: providerPath, dest: `/`})
36
+ providerPath = `${baseFolder}:${path.split('[')[1].split(']')[0]}`
37
+ providerRoutes.push({source: providerPath, dest: `${path}/index.html`})
71
38
  break;
72
39
  case provider === 'nginx':
73
40
  providerPath = `RewriteRule ^${baseFolder.replace('/', '')}.*$ ${path}/index.html [L]`
74
41
  providerRoutes.push(providerPath)
75
42
  break;
76
- case provider === 'cloudflare':
77
- if(route.isCatchAll){
78
- providerPath = `${baseFolder}/*`
79
- providerRoutes.push({source: providerPath, destination: `${path}/index.html`})
80
- break;
81
- }
82
- providerPath = `${baseFolder}/*`
83
- providerRoutes.push({source: providerPath, destination: `${path}/index.html`})
84
- break;
85
43
  }
86
44
  }else{
87
45
  let providerPath;
@@ -97,48 +55,17 @@ async function generate(){
97
55
  providerPath = `RewriteRule ^${path.replace('/', '')}/$ ${path}/index.html [L]`
98
56
  providerRoutes.push(providerPath)
99
57
  break;
100
-
101
58
 
102
59
  }
103
- }
104
- dom = preRender ? dom : '<div id="root"></div>' + `
105
- <script type="module">
106
-
60
+ }
61
+ dom = dom + `
62
+ <script type="module">
107
63
  import { render } from '/src/client.js'
108
- let ${name} = await import('/pages/${file.replace(process.cwd(), '')}')
109
- if(${name}.default){
110
- ${name} = ${name}.default
111
- }else{
112
- let keys = Object.keys(${name})
113
- ${name} = ${name}[keys[0]]
114
- }
64
+ import ${name} from '/pages/${file.replace(process.cwd(), '')}'
115
65
  import Kuai from '/src/router.js'
116
66
  let kuai = new Kuai()
117
- ${
118
- routes[i].params ?
119
- routes[i].params.map((param) => {
120
- let name = param.name
121
- let file = param.file.replace(/\\/g, '/').replace('\/\/', '/').replace(process.cwd().replace(/\\/g, '/'), '').split('/pages')[1].replace('.tsx', '.js').replace('.jsx', '.js')
122
- return `
123
- // handle if default or named
124
- let ${name} = await import('/pages/${file}')
125
- if(${name}.default){
126
- ${name} = ${name}.default
127
- }else{
128
- let keys = Object.keys(${name})
129
- ${name} = ${name}[keys[0]]
130
- }
131
- kuai.get('${param.baseFolder}:${name}', (c) => {
132
- render(${name}, ${
133
- isHtml ? `document.documentElement`: `document.body.firstChild`
134
- }, c.req, c.res)
135
- })`
136
- }).join('\n') : ''
137
- }
138
67
  kuai.get('${path}', (c) => {
139
- render(${name}, ${
140
- isHtml ? `document.documentElement`: `document.body.firstChild`
141
- }, c.req, c.res)
68
+ render(${name}, document.getElementById('root'), c.req, c.res)
142
69
  })
143
70
 
144
71
  kuai.listen()
@@ -173,7 +100,7 @@ Header add x-powered-by "vaderjs"
173
100
  </IfModule>
174
101
  `
175
102
  fs.writeFileSync(process.cwd() + '/.htaccess', full)
176
- break;
103
+ break;
177
104
  }
178
105
  console.log(`\x1b[32mSuccess\x1b[0m - Static files generated`)
179
106
 
package/router/index.ts CHANGED
@@ -56,11 +56,7 @@ function spawn_ssr_server(config: any ){
56
56
  let fileType = handleContentTypes(file)
57
57
  if(fs.existsSync(file)){
58
58
  let content = await Bun.file(file).text()
59
- let data = Buffer.from(content, 'utf-8');
60
- const compressed = Bun.gzipSync(data);
61
- return new Response(compressed, {status: 200, headers: {'Content-Type': fileType, 'x-powered-by': 'Vader',
62
- 'Content-Encoding':'gzip',
63
- ...config?.routes.find(route => route.pathname === "*" || route.pathname === url.pathname)?.headers}})
59
+ return new Response(content, {status: 200, headers: {'Content-Type': fileType, 'x-powered-by': 'Vader'}})
64
60
  }
65
61
  }
66
62
  let routeMatch = routesRouter.match(url.pathname)
@@ -80,7 +76,6 @@ function spawn_ssr_server(config: any ){
80
76
  if(response instanceof Response){
81
77
  // set x-powered-by header
82
78
  response.headers.set('x-powered-by', 'Vader')
83
- response.headers.set('Content-Type', 'text/html')
84
79
  return response
85
80
  }
86
81
  throw new Error(`Route ${routeMatch.filePath.split('/routes')[1]} did not return a response in file ${routeMatch.filePath}`)
@@ -94,12 +89,11 @@ function spawn_ssr_server(config: any ){
94
89
  }
95
90
  }
96
91
  let server = Bun.serve({
97
- port: config?.env?.PORT || 3000,
98
- hostname: config?.host?.hostname || 'localhost',
92
+ port: config.env.PORT || 3000,
93
+ hostname: config.host.hostname || 'localhost',
99
94
  reusePort: true,
100
95
  lowMemoryMode: true,
101
96
  development: false,
102
- ...(config?.Router?.tls && {tls: {cert: config.Router.tls.cert, key: config.Router.tls.key}}),
103
97
  websocket: {
104
98
  message(event){
105
99
 
@@ -143,42 +137,21 @@ function spawnServer(config: any){
143
137
  if(url.pathname.includes('.')){
144
138
  url.pathname = url.pathname.replace('/\/', '/')
145
139
  url.pathname = url.pathname.replace('/build/', '')
146
-
147
- let file = process.cwd() + '/build' + url.pathname
140
+ if(url.pathname.includes('/build')){
141
+ url.pathname = url.pathname.replace('/build', '')
142
+ }
143
+ let file = process.cwd() + '/build' + url.pathname
148
144
  let fileType = handleContentTypes(file)
149
145
  if(fs.existsSync(file)){
150
146
  let content = await Bun.file(file).text()
151
- let data = Buffer.from(content, 'utf-8');
152
- const compressed = Bun.gzipSync(data);
153
-
154
- return new Response(compressed, {status: 200, headers: {'Content-Type': fileType, 'x-powered-by': 'Vader', 'x-powered-by': 'Vader',
155
- 'Content-Encoding':'gzip',
156
- 'Accept-Encoding': 'gzip, deflate, br','Connection': 'keep-alive', 'Cache-Control': 'no-cache', 'Pragma': 'no-cache', 'Expires': '0', ...config?.Router?.headers}})
147
+ return new Response(content, {status: 200, headers: {'Content-Type': fileType, 'x-powered-by': 'Vader'}})
157
148
  }
158
149
  }
159
150
  let route = router.match(url.pathname)
160
151
  if(route){
161
- let isParamRoute = route.filePath.includes('[') && route.filePath.includes(']')
162
152
  let path = route.filePath.split('/pages')[1].replace('.jsx', '.js').replace('.tsx', '.js').replace('.ts', '.js')
163
- path = isParamRoute ? 'index.html' : path
164
153
  let html = fs.readFileSync(process.cwd() + `/build/${path.replace('.js', '.html')}`).toString()
165
- html = html + `
166
- <script>
167
- let ws = new WebSocket('ws://${config.host.hostname || 'localhost'}:${config.env.PORT || 3000}')
168
- ws.onmessage = function(event){
169
- console.log(event.data)
170
- }
171
- ws.onclose = function(event){
172
- window.location.reload()
173
- }
174
- </script>
175
- `
176
- const data = Buffer.from(html, 'utf-8');
177
- const compressed = Bun.gzipSync(data);
178
- return new Response(compressed, {status: 200, headers: {'Content-Type': 'text/html', 'x-powered-by': 'Vader',
179
- 'Content-Encoding':'gzip',
180
- 'Accept-Encoding': 'gzip, deflate, br','Connection': 'keep-alive', 'Cache-Control': 'no-cache', 'Pragma': 'no-cache', 'Expires': '0',
181
- ...config?.Router?.headers}})
154
+ return new Response(html, {status: 200, headers: {'Content-Type': 'text/html', 'x-powered-by': 'Vader'}})
182
155
  }
183
156
  return new Response('Not Found', {status: 404})
184
157
  }
@@ -198,7 +171,7 @@ export default {
198
171
  if(!globalThis.isListening){
199
172
  let config = require(process.cwd() + '/vader.config.js').default
200
173
  if(process.env.mode === 'production'){
201
- console.log(`\x1b[32msuccess \x1b[0m- listening on port ${config.env.PORT || 3000}`)
174
+ console.log(`Listening at - http://${config.host.hostname}:${config.env.PORT}`)
202
175
  spawnServer(config)
203
176
  }
204
177
  config?.env?.SSR ? spawn_ssr_server(config ) : spawnServer(config)
package/server/index.js CHANGED
@@ -47,22 +47,8 @@ class Component {
47
47
  }
48
48
 
49
49
  }
50
- export async function renderToString(element, args = []) {
51
- globalThis.isServer = true
52
- globalThis.preRender = true
53
- let data = typeof element === 'function' ? await element(args) : element
54
- if(data?.tagName === 'html'){
55
- let body = data.querySelector('body') || new Document().createElement('body')
56
- let innerHTML = body.innerHTML
57
- innerHTML = `${innerHTML}`
58
- body.tagName = 'div'
59
- body.setAttribute('id', 'root')
60
- body.innerHTML = innerHTML
61
- data.removeChild(data.querySelector('body'))
62
- data.appendChild(body)
63
- }else if(data){
64
- data.firstChild.setAttribute('id', 'root')
65
- }
50
+ export async function renderToString(element, args = []) {
51
+ let data = typeof element === 'function' ? await element(args) : element
66
52
  let doc = new Document()
67
53
  let el = doc.createElement(data)
68
54
 
@@ -1,93 +0,0 @@
1
- //@ts-nocheck
2
- function checkIFtailwindInstalled() {
3
- try {
4
- require.resolve('tailwindcss');
5
- return true;
6
- } catch (e) {
7
- return false;
8
- }
9
- }
10
-
11
-
12
- export default {
13
- name: "tailwind",
14
- description: "A plugin to install tailwindcss",
15
- once: true,
16
- init: async () => {
17
- let config = require(process.cwd() + "/vader.config.js").default;
18
- const fs = require("fs");
19
- const path = require("path");
20
- const { exec} = require("child_process");
21
- const tailwindConfig = `
22
- /** @type {import('tailwindcss').Config} */
23
- module.exports = {
24
- content: ['./src/**/*.{jsx,tsx,js,ts}', './pages/**/*.{jsx,tsx,js,ts}', './components/**/*.{jsx,tsx,js,ts}'],
25
- theme: {
26
- ${
27
- config?.tailwind?.theme ? JSON.stringify(config.tailwind.theme, null, 2) : ``
28
- }
29
- },
30
- plugins: [
31
- ${
32
- config?.tailwind?.plugins ? config?.tailwind?.plugins.map((plugin) => {
33
- return `require('${plugin}')`
34
- }).join(",") : ``
35
- }
36
- ]
37
- }
38
- `;
39
- fs.writeFileSync(
40
- path.join(process.cwd(), "tailwind.config.js"),
41
- tailwindConfig
42
- );
43
- if (!checkIFtailwindInstalled()) {
44
- console.log(`\x1b[36mwait \x1b[0m - installing tailwindcss & ${config?.tailwind?.plugins ? config?.tailwind?.plugins.length + " plugins" : ""} (First time only)`);
45
- let npmPath = process.platform === "win32" ? "npm.cmd" : "npm";
46
- Bun.spawnSync({
47
- cmd: [npmPath, "install", "tailwindcss", "postcss", "autoprefixer" , ...config?.tailwind?.plugins || []],
48
- cwd: process.cwd(),
49
- stderr: "inherit",
50
- })
51
- console.log(`\x1b[32msuccess \x1b[0m - tailwindcss installed`)
52
-
53
-
54
- const postcssConfig = `
55
- module.exports = {
56
- plugins: {
57
- tailwindcss: {},
58
- autoprefixer: {},
59
- },
60
- }
61
- `;
62
- fs.mkdirSync(path.join(process.cwd(), "src/public/styles"), {
63
- recursive: true,
64
- });
65
- fs.writeFileSync(
66
- path.join(process.cwd(), "src/public/styles/tailwind.css"),
67
- `@import 'tailwindcss/base'; @import 'tailwindcss/components'; @import 'tailwindcss/utilities';`
68
- );
69
- fs.writeFileSync(
70
- path.join(process.cwd(), "postcss.config.js"),
71
- postcssConfig
72
- );
73
- }
74
-
75
- if(!fs.existsSync(path.join(process.cwd(), "src/public/styles/tailwind.css"))){
76
- fs.mkdirSync(path.join(process.cwd(), "src/public/styles"), {
77
- recursive: true,
78
- });
79
- fs.writeFileSync(
80
- path.join(process.cwd(), "src/public/styles/tailwind.css"),
81
- `@import 'tailwindcss/base'; @import 'tailwindcss/components'; @import 'tailwindcss/utilities';`
82
- );
83
- }
84
-
85
- let cmd = process.platform === "win32" ? "npx.cmd" : "npx";
86
- Bun.spawn({
87
- cmd: [ cmd, "tailwindcss", process.cwd() + '/tailwind.config.js' , "-i", "src/public/styles/tailwind.css", "-o", config?.tailwind?.output || "public/styles/tailwind.css", "--minify"],
88
- cwd: process.cwd(),
89
- stdin: "inherit",
90
- stderr: "inherit",
91
- });
92
- },
93
- }
File without changes