duto 0.261001.0 → 0.261012.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.
Files changed (32) hide show
  1. package/package.json +22 -26
  2. package/src/commands/templates/pages/components/html.tsx +55 -0
  3. package/src/commands/templates/pages/components/theme-select.tsx +60 -0
  4. package/src/commands/templates/pages/i18n/en.ts +6 -0
  5. package/src/commands/templates/pages/i18n/pt-br.ts +6 -0
  6. package/src/commands/templates/pages/pages/404.tsx +1 -1
  7. package/src/commands/templates/pages/pages/blog/[slug].tsx +88 -0
  8. package/src/commands/templates/pages/pages/blog/index.tsx +74 -0
  9. package/src/commands/templates/pages/pages/index.tsx +17 -7
  10. package/src/commands/templates/pages/pages/layout.tsx +5 -3
  11. package/src/commands/templates/pages/public/favicon.ico +0 -0
  12. package/src/commands/templates/pages/public/favicon.svg +1 -0
  13. package/src/commands/templates/pages/style.css +110 -7
  14. package/src/commands/templates/pages/tsconfig.json +2 -0
  15. package/src/pages/cli/commands/build.ts +1 -2
  16. package/src/pages/cli/utils.ts +8 -6
  17. package/src/pages/client/app.tsx +177 -28
  18. package/src/pages/client/link.ts +15 -41
  19. package/src/pages/client/storage.ts +1 -1
  20. package/src/pages/client/theme.ts +49 -0
  21. package/src/pages/compiler/ast.ts +13 -0
  22. package/src/pages/compiler/bun-plugin.ts +245 -0
  23. package/src/pages/compiler/constants.ts +2 -0
  24. package/src/pages/compiler/index.ts +44 -23
  25. package/src/pages/compiler/meta.ts +7 -31
  26. package/src/pages/compiler/types.ts +15 -25
  27. package/src/pages/components/link.tsx +11 -19
  28. package/src/pages/i18n/client.ts +3 -4
  29. package/src/pages/index.ts +4 -21
  30. package/src/server/app.ts +2 -1
  31. package/src/pages/client/router.ts +0 -63
  32. package/src/pages/compiler/vite-plugin.ts +0 -345
@@ -1,345 +0,0 @@
1
- // REF: https://github.com/tailwindlabs/tailwindcss/blob/main/packages/%40tailwindcss-vite/src/index.ts
2
-
3
- import { existsSync, rmSync } from 'node:fs'
4
- import { join } from 'node:path'
5
- import { defineConfig } from 'vite'
6
-
7
- import preact from '@preact/preset-vite'
8
- import tailwind from '@tailwindcss/vite'
9
- import { JSJSON } from 't0n'
10
-
11
- import { EXT_RE } from './constants'
12
- import { getChunk, setAsset, setChunk, setEntry } from './assets'
13
- import { renderPage } from '.'
14
- import { removeExports, resolveImport } from './ast'
15
- import { getMetadata } from './meta'
16
-
17
- import type {
18
- UserConfig, ConfigEnv, ResolvedConfig,
19
- // PreviewServer,
20
- // ViteDevServer,
21
- EnvironmentOptions,
22
- PluginOption,
23
- } from 'vite'
24
- import type { Metadata, PluginOptions } from './types'
25
- import { _pages, _root } from '@/utils'
26
-
27
- const VIRTUAL_ID = ':duto'
28
- const RESOLVED_ID = '\0'+ VIRTUAL_ID
29
-
30
- export const config = (opts: UserConfig & PluginOptions) => { // @ts-ignore
31
- if (!opts.root) opts.root = _root
32
- if (!opts.pagesDir) opts.pagesDir = 'pages',
33
-
34
- opts.logLevel = 'silent'
35
- opts.plugins = [
36
- ...(opts.plugins || []),
37
- preact(),
38
- tailwind(),
39
- plugin(opts),
40
- ]
41
-
42
- return defineConfig(opts)
43
- }
44
-
45
- // TODO: remover..
46
- export default config
47
-
48
- let metadata: Metadata
49
- export function meta() {
50
- return metadata
51
- }
52
-
53
- export function plugin(options: PluginOptions = {}): PluginOption[] {
54
- let config: ResolvedConfig
55
- const {
56
- root = _root,
57
- pagesDir = 'pages',
58
- } = options
59
-
60
- const PAGES_RE = new RegExp(`\/${pagesDir}\/.*\.(tsx?|jsx?)$`, 'i')
61
- const stripTarget = new Set(['getStaticProps'])
62
-
63
- return [
64
- {
65
- name: 'duto:preact-environment',
66
-
67
- configEnvironment(name, options) {
68
- const opts: EnvironmentOptions = {optimizeDeps: {}, resolve: {}}
69
-
70
- if (name === 'client') {
71
- opts.optimizeDeps!.include = [
72
- 'preact',
73
- 'preact/jsx-runtime',
74
- ]
75
- }
76
-
77
- opts.resolve = {dedupe: ['preact/compat', 'preact']}
78
-
79
- if (name === 'client')
80
- opts.optimizeDeps!.include!.push(
81
- 'preact/compat',
82
- // 'preact/test-utils',
83
- 'preact/compat/jsx-runtime',
84
- )
85
-
86
- if (
87
- !options.resolve?.noExternal &&
88
- (name === 'ssr' || name === 'prerender')
89
- ) {
90
- // noExternal React entrypoints to be bundled, resolved, and aliased by Vite
91
- opts.resolve!.noExternal = [
92
- 'react',
93
- 'react-dom',
94
- 'react-dom/test-utils',
95
- 'react/jsx-runtime',
96
- ]
97
- }
98
-
99
- return opts
100
- },
101
- },
102
-
103
- {
104
- name: 'duto:scan',
105
- enforce: 'pre',
106
-
107
- async config(conf: UserConfig, env: ConfigEnv) {
108
- metadata = await getMetadata(root as string, pagesDir)
109
-
110
- if (conf.build) {
111
- // conf.build.emptyOutDir = false
112
- conf.build.copyPublicDir = false
113
- conf.build.manifest = false
114
- conf.build.modulePreload = { polyfill: false }
115
-
116
- conf.build.minify = metadata.minify
117
- conf.build.cssMinify = metadata.minify
118
-
119
- conf.build.rolldownOptions = conf.build.rolldownOptions || {}
120
- conf.build.rolldownOptions.preserveEntrySignatures = 'exports-only' ///
121
- conf.build.rolldownOptions.input = [
122
- ...metadata.routes.map(r => r.is404 ? '' : r.fullFilePath).filter(Boolean),
123
- ':duto/client/app.tsx',
124
- // ':duto/not-found.tsx',
125
- // ...Object.keys(metadata.pages),
126
- // ...metadata.assets,
127
- ]
128
-
129
- const filePrefix = metadata.minify ? '' : '[name].'
130
- // conf.build.rolldownOptions.input = ':duto/client/app.tsx'
131
- conf.build.rolldownOptions.output = {
132
- hoistTransitiveImports: false,
133
- format: 'esm',
134
- minifyInternalExports: metadata.minify,
135
- preserveModulesRoot: '/',
136
- assetFileNames: filePrefix +'[hash][extname]',
137
- entryFileNames: filePrefix +'[hash].js',
138
- chunkFileNames: filePrefix +'[hash].js',
139
-
140
- // chunkFileNames: '[name].[hash].js',
141
- // entryFileNames: 'assets/[name].js',
142
- // chunkFileNames: 'assets/chunks/[name]-[hash].js',
143
- // assetFileNames: 'assets/[name][extname]',
144
-
145
- // manualChunks: {
146
- // vendor: ['preact', '@preact/signals', 'wouter-preact'],
147
- // },
148
- // preserveModules: true,
149
- }
150
- }
151
-
152
- return conf
153
- },
154
-
155
- async configResolved(c) {
156
- config = c
157
- },
158
-
159
- resolveId(id) {
160
- if (id === VIRTUAL_ID) return RESOLVED_ID
161
-
162
- if (id.startsWith(':root')) {
163
- for (const f of [
164
- 'style.css',
165
- 'styles.css',
166
- 'styles/index.css',
167
- 'style/index.css',
168
- 'tailwind.css',
169
- 'tailwindcss.css',
170
- 'styles/tailwind.css',
171
- 'styles/tailwindcss.css',
172
- ]) {
173
- const path = join(config.root, f)
174
- if (existsSync(path)) {
175
- setEntry(id, path)
176
- return path
177
- }
178
- }
179
-
180
- return null
181
- }
182
-
183
- if (!id.startsWith(VIRTUAL_ID)) return null
184
-
185
- if (EXT_RE.test(id) && id.includes('/')) {
186
- const path = join(_pages, id.replace(VIRTUAL_ID, ''))
187
- setEntry(id, path)
188
- return path
189
- }
190
-
191
- if (id.endsWith('/hmr') && metadata.hmr)
192
- return join(_pages, 'client', id.replace(VIRTUAL_ID, '') + '.ts')
193
-
194
- return id.replace(VIRTUAL_ID, RESOLVED_ID)
195
- },
196
-
197
- async load(id) {
198
- if (!id.startsWith(RESOLVED_ID)) return
199
-
200
- if (id.endsWith('/i18n'))
201
- return metadata.i18n.string
202
-
203
- return metadata.string
204
- },
205
-
206
- generateBundle(_, bundle) {
207
- // const moduleIds = this.getModuleIds()
208
- // for (const id of moduleIds)
209
- // console.error(id)
210
-
211
- // TODO: rever isso...
212
- for (const key in bundle) {
213
- const file = bundle[key]
214
-
215
- if (file.type === 'chunk' && file.isEntry) {
216
- setChunk(file.facadeModuleId, '/'+ file.fileName)
217
- continue
218
- }
219
-
220
- if (file.type === 'asset' && file?.originalFileName?.endsWith('duto/pages/client/app.tsx'))
221
- file.source += 'i-i{display:contents}'
222
- // file.source += 'd-b,d-p,i-d,i-s,i-i{display:contents}'
223
-
224
- if (file.type === 'asset' && file.fileName.endsWith('.css')) {
225
- setAsset(resolveImport(file.originalFileName as string, metadata.root, metadata.aliases), '/'+ file.fileName)
226
- continue
227
- }
228
-
229
- // console.error(file.fileName)
230
- // console.error(file.type)
231
- // console.error(file.viteMetadata)
232
- // if (file.type !== 'chunk' || !file.isEntry) continue
233
- }
234
- },
235
-
236
- },
237
-
238
- // {
239
- // name: 'duto:routes-inject',
240
- // enforce: 'post',
241
- // generateBundle(_, bundle) {
242
- // // monta o mapa a partir dos inputs de metadata.routes
243
- // const routeMap: Record<string, string> = {}
244
- // for (const r of metadata.routes) {
245
- // if (r.is404) continue
246
- // // encontra o chunk cujo facadeModuleId bate com r.fullFilePath
247
- // for (const [fileName, chunk] of Object.entries(bundle)) {
248
- // if (chunk.type === 'chunk' && chunk.facadeModuleId === r.fullFilePath) {
249
- // routeMap[r.path] = fileName
250
- // break
251
- // }
252
- // }
253
- // }
254
-
255
- // // injeta no chunk do app
256
- // for (const chunk of Object.values(bundle)) {
257
- // if (chunk.type !== 'chunk') continue
258
- // if (chunk.facadeModuleId?.includes('app.tsx') || chunk.code.includes('__DUTO_ROUTES__')) {
259
- // chunk.code = chunk.code.replace(
260
- // '__DUTO_ROUTES__',
261
- // JSON.stringify(routeMap)
262
- // )
263
- // }
264
- // }
265
- // }
266
- // },
267
- {
268
- name: 'duto:build',
269
- enforce: 'pre',
270
- apply: 'build',
271
-
272
- async buildStart() {
273
- // if (!server) {
274
- // const { createServer } = await import('vite')
275
- // server = await createServer({ server: {middlewareMode: true} })
276
- // }
277
-
278
-
279
- // teste de import de assets
280
- // for (const file of metadata.assets) {
281
- // const id = await this.resolve(file)
282
- // if (!id) continue
283
-
284
- // console.error(id)
285
- // console.error(relative(metadata.root, file).replace(/\.(ts|tsx)$/, '.js'),)
286
-
287
- // this.emitFile({
288
- // type: 'chunk',
289
- // id: id.id,
290
- // implicitlyLoadedAfterOneOf: [
291
- // ':duto/app.tsx',
292
- // ]
293
- // // fileName: 'assets/[name]-[hash][extname]',
294
- // // fileName: relative(metadata.root, file).replace(/\.(ts|tsx)$/, '.js'),
295
- // })
296
- // }
297
-
298
- },
299
-
300
- async closeBundle() {
301
- for (const [_filePath, page] of metadata.pages)
302
- await renderPage(metadata, config, page)
303
- // const mod = await server.ssrLoadModule(_filePath)
304
-
305
- rmSync(join(metadata.root, 'tmp'), {recursive: true, force: true})
306
- // await server.close()
307
-
308
- const outPath = join(config.root, config.build.outDir)
309
- const entry = Bun.file(join(outPath, getChunk(':duto/client/app.tsx')))
310
- let entryContent = await entry.text()
311
-
312
- for (const r of metadata.routes.filter(r => !r.is404))
313
- entryContent = entryContent.replace(r.fullFilePath, getChunk(r.fullFilePath.replace(config.root, '')))
314
-
315
- await entry.write(entryContent)
316
-
317
- // i18n
318
- for (const locale of metadata.i18n.locales) {
319
- const intlPath = join(metadata.root, 'i18n', locale + '.ts')
320
- if (existsSync(intlPath)) {
321
- const intlMod = await import(intlPath)
322
- await Bun.write(
323
- join(outPath, locale +'.js'),
324
- `var a=${JSJSON({
325
- routes: intlMod.routes ?? intlMod.default?.routes,
326
- messages: intlMod.messages ?? intlMod.default?.messages,
327
- })};export { a as default }`
328
- )
329
- }
330
- }
331
- },
332
-
333
- // TODO: precisa ser aqui mesmo pois se a pagina for importada no entry, pode incluir codigo nao usado no chunck/bundle
334
- async transform(code, id) {
335
- if (!PAGES_RE.test(id) || id.includes('node_modules')) return null
336
- // console.log(this.getModuleInfo(id))
337
-
338
- const stripped = removeExports(id, code, stripTarget)
339
-
340
- return (!stripped || stripped === code) ? null : { code: stripped, map: null }
341
- },
342
-
343
- },
344
- ]
345
- }