orga-build 0.4.0 → 0.5.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/lib/__tests__/build.test.d.ts +2 -0
- package/lib/__tests__/build.test.d.ts.map +1 -0
- package/lib/__tests__/build.test.js +64 -0
- package/lib/build.d.ts.map +1 -1
- package/lib/build.js +55 -63
- package/lib/serve.d.ts.map +1 -1
- package/lib/serve.js +0 -1
- package/lib/vite.d.ts.map +1 -1
- package/lib/vite.js +15 -17
- package/package.json +6 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.test.d.ts","sourceRoot":"","sources":["build.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { test, describe, before, after } from 'node:test'
|
|
2
|
+
import assert from 'node:assert'
|
|
3
|
+
import fs from 'node:fs/promises'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
import { build } from '../build.js'
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const fixtureDir = path.join(__dirname, 'fixtures')
|
|
10
|
+
const outDir = path.join(__dirname, '.test-output')
|
|
11
|
+
|
|
12
|
+
describe('orga-build', () => {
|
|
13
|
+
before(async () => {
|
|
14
|
+
await fs.mkdir(fixtureDir, { recursive: true })
|
|
15
|
+
// Create minimal fixture
|
|
16
|
+
await fs.writeFile(
|
|
17
|
+
path.join(fixtureDir, 'index.org'),
|
|
18
|
+
`#+title: Test Page
|
|
19
|
+
|
|
20
|
+
* Hello World
|
|
21
|
+
|
|
22
|
+
This is a test page.
|
|
23
|
+
`
|
|
24
|
+
)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
after(async () => {
|
|
28
|
+
await fs.rm(outDir, { recursive: true, force: true })
|
|
29
|
+
await fs.rm(fixtureDir, { recursive: true, force: true })
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('builds org files to HTML', async () => {
|
|
33
|
+
await build({
|
|
34
|
+
root: fixtureDir,
|
|
35
|
+
outDir: outDir,
|
|
36
|
+
containerClass: [],
|
|
37
|
+
vitePlugins: [],
|
|
38
|
+
preBuild: [],
|
|
39
|
+
postBuild: []
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Check output exists
|
|
43
|
+
const indexPath = path.join(outDir, 'index.html')
|
|
44
|
+
const indexExists = await fs
|
|
45
|
+
.access(indexPath)
|
|
46
|
+
.then(() => true)
|
|
47
|
+
.catch(() => false)
|
|
48
|
+
assert.ok(indexExists, 'index.html should exist')
|
|
49
|
+
|
|
50
|
+
// Check content
|
|
51
|
+
const html = await fs.readFile(indexPath, 'utf-8')
|
|
52
|
+
assert.ok(html.includes('<title>Test Page</title>'), 'should have title')
|
|
53
|
+
assert.ok(html.includes('Hello World'), 'should have heading content')
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('generates assets directory', async () => {
|
|
57
|
+
const assetsDir = path.join(outDir, 'assets')
|
|
58
|
+
const assetsExists = await fs
|
|
59
|
+
.access(assetsDir)
|
|
60
|
+
.then(() => true)
|
|
61
|
+
.catch(() => false)
|
|
62
|
+
assert.ok(assetsExists, 'assets directory should exist')
|
|
63
|
+
})
|
|
64
|
+
})
|
package/lib/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["build.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["build.js"],"names":[],"mappings":"AAqBA;;GAEG;AACH,qEAFW,OAAO,aAAa,EAAE,MAAM,iBAoJtC;AA9JD;;;;EAIC"}
|
package/lib/build.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import { createRequire } from 'node:module'
|
|
3
|
-
import {
|
|
3
|
+
import { createBuilder } from 'vite'
|
|
4
4
|
import { setupOrga } from './orga.js'
|
|
5
5
|
import react from '@vitejs/plugin-react'
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
7
7
|
import { copy, emptyDir, ensureDir } from './fs.js'
|
|
8
8
|
import { pluginFactory } from './vite.js'
|
|
9
9
|
import fs from 'fs/promises'
|
|
10
|
-
import assert from 'node:assert'
|
|
11
10
|
|
|
12
11
|
const require = createRequire(import.meta.url)
|
|
13
12
|
|
|
@@ -17,6 +16,9 @@ export const alias = {
|
|
|
17
16
|
wouter: path.dirname(require.resolve('wouter'))
|
|
18
17
|
}
|
|
19
18
|
|
|
19
|
+
const ssrEntry = fileURLToPath(new URL('./ssr.jsx', import.meta.url))
|
|
20
|
+
const clientEntry = fileURLToPath(new URL('./client.jsx', import.meta.url))
|
|
21
|
+
|
|
20
22
|
/**
|
|
21
23
|
* @param {import('./config.js').Config} config
|
|
22
24
|
*/
|
|
@@ -26,7 +28,6 @@ export async function build({
|
|
|
26
28
|
containerClass,
|
|
27
29
|
vitePlugins = []
|
|
28
30
|
}) {
|
|
29
|
-
/* --- prepare folders, out, ssr, client --- */
|
|
30
31
|
await emptyDir(outDir)
|
|
31
32
|
const ssrOutDir = path.join(outDir, '.ssr')
|
|
32
33
|
const clientOutDir = path.join(outDir, '.client')
|
|
@@ -38,80 +39,71 @@ export async function build({
|
|
|
38
39
|
...vitePlugins
|
|
39
40
|
]
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
await viteBuild({
|
|
42
|
+
// Shared config with environment-specific build settings
|
|
43
|
+
const builder = await createBuilder({
|
|
44
44
|
root,
|
|
45
45
|
plugins,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
46
|
+
resolve: { alias },
|
|
47
|
+
ssr: { noExternal: true },
|
|
48
|
+
environments: {
|
|
49
|
+
ssr: {
|
|
50
|
+
build: {
|
|
51
|
+
ssr: true,
|
|
52
|
+
outDir: ssrOutDir,
|
|
53
|
+
cssCodeSplit: false,
|
|
54
|
+
emptyOutDir: true,
|
|
55
|
+
minify: false,
|
|
56
|
+
rollupOptions: {
|
|
57
|
+
input: ssrEntry,
|
|
58
|
+
output: {
|
|
59
|
+
entryFileNames: '[name].mjs',
|
|
60
|
+
chunkFileNames: '[name]-[hash].mjs'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
55
63
|
}
|
|
56
64
|
},
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
client: {
|
|
66
|
+
build: {
|
|
67
|
+
outDir: clientOutDir,
|
|
68
|
+
cssCodeSplit: false,
|
|
69
|
+
emptyOutDir: true,
|
|
70
|
+
assetsDir: 'assets',
|
|
71
|
+
rollupOptions: {
|
|
72
|
+
input: clientEntry,
|
|
73
|
+
preserveEntrySignatures: 'allow-extension'
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
65
77
|
}
|
|
66
78
|
})
|
|
67
79
|
|
|
68
|
-
|
|
80
|
+
// Build SSR first to get render function and pages
|
|
81
|
+
console.log('preparing ssr bundle...')
|
|
82
|
+
await builder.build(builder.environments.ssr)
|
|
69
83
|
|
|
70
84
|
const { render, pages } = await import(
|
|
71
85
|
pathToFileURL(path.join(ssrOutDir, 'ssr.mjs')).toString()
|
|
72
86
|
)
|
|
73
87
|
|
|
74
|
-
|
|
75
|
-
const _clientResult = await
|
|
76
|
-
root,
|
|
77
|
-
plugins,
|
|
78
|
-
build: {
|
|
79
|
-
cssCodeSplit: false,
|
|
80
|
-
emptyOutDir: true,
|
|
81
|
-
rollupOptions: {
|
|
82
|
-
input: fileURLToPath(new URL('./client.jsx', import.meta.url)),
|
|
83
|
-
preserveEntrySignatures: 'allow-extension'
|
|
84
|
-
},
|
|
85
|
-
assetsDir: 'assets',
|
|
86
|
-
outDir: clientOutDir
|
|
87
|
-
},
|
|
88
|
-
ssr: {
|
|
89
|
-
noExternal: true
|
|
90
|
-
},
|
|
91
|
-
resolve: {
|
|
92
|
-
alias: alias
|
|
93
|
-
}
|
|
94
|
-
})
|
|
88
|
+
// Build client bundle
|
|
89
|
+
const _clientResult = await builder.build(builder.environments.client)
|
|
95
90
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
assert('output' in _clientResult)
|
|
104
|
-
clientResult = _clientResult
|
|
105
|
-
}
|
|
91
|
+
// Normalize build result to single RollupOutput
|
|
92
|
+
const clientOutput = Array.isArray(_clientResult)
|
|
93
|
+
? _clientResult[0].output
|
|
94
|
+
: 'output' in _clientResult
|
|
95
|
+
? _clientResult.output
|
|
96
|
+
: null
|
|
97
|
+
if (!clientOutput) throw new Error('Unexpected client build result')
|
|
106
98
|
|
|
107
99
|
/* --- get from client bundle result: entry chunk, css chunks --- */
|
|
108
|
-
const entryChunk =
|
|
109
|
-
|
|
110
|
-
|
|
100
|
+
const entryChunk = clientOutput.find(
|
|
101
|
+
(/** @type {any} */ c) => c.type === 'chunk' && c.isEntry
|
|
102
|
+
)
|
|
111
103
|
|
|
112
|
-
const cssChunks =
|
|
113
|
-
|
|
114
|
-
|
|
104
|
+
const cssChunks = clientOutput.filter(
|
|
105
|
+
(/** @type {any} */ c) => c.type === 'asset' && c.fileName.endsWith('.css')
|
|
106
|
+
)
|
|
115
107
|
|
|
116
108
|
/* --- get html template, inject entry js and css --- */
|
|
117
109
|
const template = await fs.readFile(
|
|
@@ -157,11 +149,11 @@ export async function build({
|
|
|
157
149
|
`
|
|
158
150
|
)
|
|
159
151
|
const css = cssChunks
|
|
160
|
-
.map((c) => `<link rel="stylesheet" href="/${c.fileName}">`)
|
|
152
|
+
.map((/** @type {any} */ c) => `<link rel="stylesheet" href="/${c.fileName}">`)
|
|
161
153
|
.join('\n')
|
|
162
154
|
html = html.replace(
|
|
163
155
|
'<script type="module" src="/@orga-build/main.js"></script>',
|
|
164
|
-
`<script type="module" src="/${entryChunk
|
|
156
|
+
`<script type="module" src="/${entryChunk?.fileName}"></script>`
|
|
165
157
|
)
|
|
166
158
|
|
|
167
159
|
html = html.replace('</head>', `${css}</head>`)
|
package/lib/serve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["serve.js"],"names":[],"mappings":"AAQA;;;GAGG;AACH,8BAHW,OAAO,aAAa,EAAE,MAAM,SAC5B,MAAM,
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["serve.js"],"names":[],"mappings":"AAQA;;;GAGG;AACH,8BAHW,OAAO,aAAa,EAAE,MAAM,SAC5B,MAAM,iBA4ChB"}
|
package/lib/serve.js
CHANGED
package/lib/vite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["vite.js"],"names":[],"mappings":"AASA;;;;GAIG;AACH,uCAHG;IAAwB,GAAG,EAAnB,MAAM;CACd,GAAU,OAAO,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["vite.js"],"names":[],"mappings":"AASA;;;;GAIG;AACH,uCAHG;IAAwB,GAAG,EAAnB,MAAM;CACd,GAAU,OAAO,MAAM,EAAE,MAAM,CA2JjC"}
|
package/lib/vite.js
CHANGED
|
@@ -19,6 +19,11 @@ export function pluginFactory({ dir }) {
|
|
|
19
19
|
name: 'vite-plugin-orga-pages',
|
|
20
20
|
enforce: 'pre',
|
|
21
21
|
config: (config, env) => ({
|
|
22
|
+
future: {
|
|
23
|
+
removePluginHookSsrArgument: 'warn',
|
|
24
|
+
removePluginHookHandleHotUpdate: 'warn',
|
|
25
|
+
removeSsrLoadModule: 'warn'
|
|
26
|
+
},
|
|
22
27
|
optimizeDeps: {
|
|
23
28
|
include: [
|
|
24
29
|
'react',
|
|
@@ -31,25 +36,18 @@ export function pluginFactory({ dir }) {
|
|
|
31
36
|
}
|
|
32
37
|
}),
|
|
33
38
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
type: 'full-reload',
|
|
45
|
-
path: '*'
|
|
46
|
-
})
|
|
47
|
-
}
|
|
48
|
-
})
|
|
39
|
+
hotUpdate() {
|
|
40
|
+
// Invalidate content module when content files change
|
|
41
|
+
const module = this.environment.moduleGraph.getModuleById(
|
|
42
|
+
contentModuleIdResolved
|
|
43
|
+
)
|
|
44
|
+
if (module) {
|
|
45
|
+
this.environment.moduleGraph.invalidateModule(module)
|
|
46
|
+
// Full reload for now; can optimize to HMR later
|
|
47
|
+
this.environment.hot.send({ type: 'full-reload', path: '*' })
|
|
48
|
+
}
|
|
49
49
|
},
|
|
50
50
|
|
|
51
|
-
buildStart() {},
|
|
52
|
-
|
|
53
51
|
async resolveId(id, importer) {
|
|
54
52
|
if (id === appEntryId) {
|
|
55
53
|
return appEntryId
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orga-build",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A simple tool that builds org-mode files into a website",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20.19.0"
|
|
8
|
+
},
|
|
6
9
|
"bin": {
|
|
7
10
|
"orga-build": "./cli.js"
|
|
8
11
|
},
|
|
@@ -60,6 +63,7 @@
|
|
|
60
63
|
"orga": "4.6.0"
|
|
61
64
|
},
|
|
62
65
|
"scripts": {
|
|
63
|
-
"clean": "fd . -e d.ts -e d.ts.map -I -x rm {}"
|
|
66
|
+
"clean": "fd . -e d.ts -e d.ts.map -I -x rm {}",
|
|
67
|
+
"test": "node --test --no-warnings \"lib/__tests__/*.test.js\""
|
|
64
68
|
}
|
|
65
69
|
}
|