orga-build 0.6.2 → 0.7.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/README.org +15 -0
- package/cli.js +1 -1
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/lib/__tests__/build.test.js +69 -5
- package/lib/app.jsx +6 -4
- package/lib/build.d.ts +1 -1
- package/lib/build.d.ts.map +1 -1
- package/lib/build.js +23 -13
- package/lib/config.d.ts +4 -0
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +6 -2
- package/lib/csr.jsx +1 -2
- package/lib/files.js +3 -3
- package/lib/fs.js +1 -1
- package/lib/orga.d.ts +3 -1
- package/lib/orga.d.ts.map +1 -1
- package/lib/orga.js +11 -5
- package/lib/plugin.d.ts +7 -2
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +9 -6
- package/lib/serve.d.ts.map +1 -1
- package/lib/serve.js +3 -2
- package/lib/ssr.jsx +2 -2
- package/lib/vite.d.ts.map +1 -1
- package/lib/vite.js +7 -17
- package/package.json +5 -4
package/README.org
CHANGED
|
@@ -82,6 +82,10 @@ export default {
|
|
|
82
82
|
// These are injected in dev SSR <head> and imported by the client entry.
|
|
83
83
|
styles: ['/style.css'],
|
|
84
84
|
|
|
85
|
+
// Extra rehype plugins appended to orga-build defaults
|
|
86
|
+
// Useful for syntax highlighting (e.g. rehype-pretty-code).
|
|
87
|
+
rehypePlugins: [],
|
|
88
|
+
|
|
85
89
|
// Additional Vite plugins
|
|
86
90
|
vitePlugins: []
|
|
87
91
|
}
|
|
@@ -95,8 +99,19 @@ export default {
|
|
|
95
99
|
| =outDir= | =string= | ='out'= | Output directory for production build |
|
|
96
100
|
| =containerClass= | =string \vert string[]= | =[]= | CSS class(es) for content wrapper |
|
|
97
101
|
| =styles= | =string[]= | =[]= | Global stylesheet URLs injected/imported explicitly |
|
|
102
|
+
| =rehypePlugins= | =PluggableList= | =[]= | Extra rehype plugins appended to orga-build defaults |
|
|
98
103
|
| =vitePlugins= | =PluginOption[]= | =[]= | Additional Vite plugins |
|
|
99
104
|
|
|
105
|
+
** Syntax Highlighting Example
|
|
106
|
+
|
|
107
|
+
#+begin_src javascript
|
|
108
|
+
import rehypePrettyCode from 'rehype-pretty-code'
|
|
109
|
+
|
|
110
|
+
export default {
|
|
111
|
+
rehypePlugins: [[rehypePrettyCode, { theme: 'github-dark' }]]
|
|
112
|
+
}
|
|
113
|
+
#+end_src
|
|
114
|
+
|
|
100
115
|
* TypeScript Setup
|
|
101
116
|
|
|
102
117
|
If you're using TypeScript and want type support for the =orga-build:content= virtual module, you need to add a reference to the type definitions.
|
package/cli.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { argv } from 'node:process'
|
|
4
4
|
import { parseArgs } from 'node:util'
|
|
5
|
-
import { loadConfig } from './lib/config.js'
|
|
6
5
|
import { build } from './lib/build.js'
|
|
6
|
+
import { loadConfig } from './lib/config.js'
|
|
7
7
|
import { serve } from './lib/serve.js'
|
|
8
8
|
|
|
9
9
|
const { positionals } = parseArgs({
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { build } from './lib/build.js'
|
|
2
|
-
export {
|
|
2
|
+
export { alias, createOrgaBuildConfig, orgaBuildPlugin } from './lib/plugin.js'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { test, describe, before, after } from 'node:test'
|
|
2
1
|
import assert from 'node:assert'
|
|
3
2
|
import fs from 'node:fs/promises'
|
|
4
3
|
import path from 'node:path'
|
|
4
|
+
import { after, before, describe, test } from 'node:test'
|
|
5
5
|
import { fileURLToPath } from 'node:url'
|
|
6
6
|
import { build } from '../build.js'
|
|
7
7
|
|
|
@@ -9,6 +9,21 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
|
9
9
|
const fixtureDir = path.join(__dirname, 'fixtures')
|
|
10
10
|
const outDir = path.join(__dirname, '.test-output')
|
|
11
11
|
|
|
12
|
+
function markCodeBlocks() {
|
|
13
|
+
/**
|
|
14
|
+
* @param {any} tree
|
|
15
|
+
*/
|
|
16
|
+
return (tree) => {
|
|
17
|
+
tree.children ||= []
|
|
18
|
+
tree.children.unshift({
|
|
19
|
+
type: 'element',
|
|
20
|
+
tagName: 'div',
|
|
21
|
+
properties: { id: 'rehype-plugin-ran' },
|
|
22
|
+
children: []
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
12
27
|
describe('orga-build', () => {
|
|
13
28
|
before(async () => {
|
|
14
29
|
await fs.mkdir(fixtureDir, { recursive: true })
|
|
@@ -27,7 +42,10 @@ Here's [[file:./docs/index.org][index page]].
|
|
|
27
42
|
Here's [[file:more.org][another page]].
|
|
28
43
|
`
|
|
29
44
|
)
|
|
30
|
-
await fs.writeFile(
|
|
45
|
+
await fs.writeFile(
|
|
46
|
+
path.join(fixtureDir, 'docs', 'index.org'),
|
|
47
|
+
'Docs index page.'
|
|
48
|
+
)
|
|
31
49
|
await fs.writeFile(path.join(fixtureDir, 'more.org'), 'Another page.')
|
|
32
50
|
await fs.writeFile(
|
|
33
51
|
path.join(fixtureDir, 'style.css'),
|
|
@@ -62,7 +80,10 @@ Here's [[file:more.org][another page]].
|
|
|
62
80
|
const html = await fs.readFile(indexPath, 'utf-8')
|
|
63
81
|
assert.ok(html.includes('<title>Test Page</title>'), 'should have title')
|
|
64
82
|
assert.ok(html.includes('Hello World'), 'should have heading content')
|
|
65
|
-
assert.ok(
|
|
83
|
+
assert.ok(
|
|
84
|
+
html.includes('href="/docs"'),
|
|
85
|
+
'should rewrite docs/index.org to /docs'
|
|
86
|
+
)
|
|
66
87
|
assert.ok(html.includes('href="/more"'), 'should rewrite more.org to /more')
|
|
67
88
|
})
|
|
68
89
|
|
|
@@ -87,10 +108,16 @@ Here's [[file:more.org][another page]].
|
|
|
87
108
|
})
|
|
88
109
|
|
|
89
110
|
const html = await fs.readFile(path.join(outDir, 'index.html'), 'utf-8')
|
|
90
|
-
assert.ok(
|
|
111
|
+
assert.ok(
|
|
112
|
+
!html.includes('href="/style.css"'),
|
|
113
|
+
'should not link raw source css path'
|
|
114
|
+
)
|
|
91
115
|
|
|
92
116
|
const cssHrefMatch = html.match(/href="\/(assets\/[^"]+\.css)"/)
|
|
93
|
-
assert.ok(
|
|
117
|
+
assert.ok(
|
|
118
|
+
cssHrefMatch,
|
|
119
|
+
'should link built css asset from assets with hashed name'
|
|
120
|
+
)
|
|
94
121
|
|
|
95
122
|
const builtCssPath = cssHrefMatch[1]
|
|
96
123
|
const builtCss = await fs.readFile(path.join(outDir, builtCssPath), 'utf-8')
|
|
@@ -99,4 +126,41 @@ Here's [[file:more.org][another page]].
|
|
|
99
126
|
'built css should include configured global style content'
|
|
100
127
|
)
|
|
101
128
|
})
|
|
129
|
+
|
|
130
|
+
test('applies custom rehype plugins from config', async () => {
|
|
131
|
+
const fixtureDirRehype = path.join(__dirname, 'fixtures-rehype')
|
|
132
|
+
const outDirRehype = path.join(__dirname, '.test-output-rehype')
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
await fs.mkdir(fixtureDirRehype, { recursive: true })
|
|
136
|
+
await fs.writeFile(
|
|
137
|
+
path.join(fixtureDirRehype, 'index.org'),
|
|
138
|
+
`#+title: Rehype Test
|
|
139
|
+
|
|
140
|
+
This page verifies custom rehype plugins.`
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
await build({
|
|
144
|
+
root: fixtureDirRehype,
|
|
145
|
+
outDir: outDirRehype,
|
|
146
|
+
containerClass: [],
|
|
147
|
+
rehypePlugins: [markCodeBlocks],
|
|
148
|
+
vitePlugins: [],
|
|
149
|
+
preBuild: [],
|
|
150
|
+
postBuild: []
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
const html = await fs.readFile(
|
|
154
|
+
path.join(outDirRehype, 'index.html'),
|
|
155
|
+
'utf-8'
|
|
156
|
+
)
|
|
157
|
+
assert.ok(
|
|
158
|
+
html.includes('rehype-plugin-ran'),
|
|
159
|
+
'should apply user-provided rehype plugins to rendered HTML'
|
|
160
|
+
)
|
|
161
|
+
} finally {
|
|
162
|
+
await fs.rm(outDirRehype, { recursive: true, force: true })
|
|
163
|
+
await fs.rm(fixtureDirRehype, { recursive: true, force: true })
|
|
164
|
+
}
|
|
165
|
+
})
|
|
102
166
|
})
|
package/lib/app.jsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import layouts from '/@orga-build/layouts'
|
|
1
|
+
import { Link, Route, Switch } from 'wouter'
|
|
3
2
|
import * as components from '/@orga-build/components'
|
|
4
|
-
import
|
|
3
|
+
import layouts from '/@orga-build/layouts'
|
|
4
|
+
import pages from '/@orga-build/pages'
|
|
5
5
|
|
|
6
6
|
export function App() {
|
|
7
7
|
const _pages = Object.entries(pages).map(([path, page]) => {
|
|
@@ -15,7 +15,9 @@ export function App() {
|
|
|
15
15
|
const layoutIds = Object.keys(layouts)
|
|
16
16
|
.filter((key) => path.startsWith(key))
|
|
17
17
|
.sort((a, b) => -a.localeCompare(b))
|
|
18
|
-
let element =
|
|
18
|
+
let element = (
|
|
19
|
+
<page.default key={path} components={{ ...components, Link, a: Link }} />
|
|
20
|
+
)
|
|
19
21
|
for (const layoutId of layoutIds) {
|
|
20
22
|
const Layout = layouts[layoutId]
|
|
21
23
|
element = (
|
package/lib/build.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @param {import('./config.js').Config} config
|
|
3
3
|
* @param {string} [projectRoot]
|
|
4
4
|
*/
|
|
5
|
-
export function build({ outDir, root, containerClass, styles, vitePlugins }: import("./config.js").Config, projectRoot?: string): Promise<void>;
|
|
5
|
+
export function build({ outDir, root, containerClass, styles, rehypePlugins, vitePlugins }: import("./config.js").Config, projectRoot?: string): Promise<void>;
|
|
6
6
|
export { alias };
|
|
7
7
|
import { alias } from './plugin.js';
|
|
8
8
|
//# sourceMappingURL=build.d.ts.map
|
package/lib/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["build.js"],"names":[],"mappings":"AAeA;;;GAGG;AACH,
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["build.js"],"names":[],"mappings":"AAeA;;;GAGG;AACH,4FAHW,OAAO,aAAa,EAAE,MAAM,gBAC5B,MAAM,iBA8JhB;;sBA1K4C,aAAa"}
|
package/lib/build.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import fs from 'node:fs/promises'
|
|
1
2
|
import path from 'node:path'
|
|
2
|
-
import { createBuilder } from 'vite'
|
|
3
3
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
4
|
+
import { createBuilder } from 'vite'
|
|
4
5
|
import { emptyDir, ensureDir, exists } from './fs.js'
|
|
5
|
-
import
|
|
6
|
-
import { createOrgaBuildConfig, alias } from './plugin.js'
|
|
6
|
+
import { alias, createOrgaBuildConfig } from './plugin.js'
|
|
7
7
|
import { escapeHtml } from './util.js'
|
|
8
8
|
import { appEntryId } from './vite.js'
|
|
9
9
|
|
|
@@ -17,13 +17,17 @@ const defaultIndexHtml = fileURLToPath(new URL('./index.html', import.meta.url))
|
|
|
17
17
|
* @param {import('./config.js').Config} config
|
|
18
18
|
* @param {string} [projectRoot]
|
|
19
19
|
*/
|
|
20
|
-
export async function build(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
export async function build(
|
|
21
|
+
{
|
|
22
|
+
outDir,
|
|
23
|
+
root,
|
|
24
|
+
containerClass,
|
|
25
|
+
styles = [],
|
|
26
|
+
rehypePlugins = [],
|
|
27
|
+
vitePlugins = []
|
|
28
|
+
},
|
|
29
|
+
projectRoot = process.cwd()
|
|
30
|
+
) {
|
|
27
31
|
await emptyDir(outDir)
|
|
28
32
|
const ssrOutDir = path.join(outDir, '.ssr')
|
|
29
33
|
const clientOutDir = outDir
|
|
@@ -33,6 +37,7 @@ export async function build({
|
|
|
33
37
|
outDir,
|
|
34
38
|
containerClass,
|
|
35
39
|
styles,
|
|
40
|
+
rehypePlugins,
|
|
36
41
|
vitePlugins
|
|
37
42
|
})
|
|
38
43
|
|
|
@@ -105,7 +110,9 @@ export async function build({
|
|
|
105
110
|
/* --- get html template, inject entry js and css --- */
|
|
106
111
|
// Check for user's index.html in project root, otherwise use default
|
|
107
112
|
const userIndexPath = path.join(projectRoot, 'index.html')
|
|
108
|
-
const indexHtmlPath = (await exists(userIndexPath))
|
|
113
|
+
const indexHtmlPath = (await exists(userIndexPath))
|
|
114
|
+
? userIndexPath
|
|
115
|
+
: defaultIndexHtml
|
|
109
116
|
const template = await fs.readFile(indexHtmlPath, { encoding: 'utf-8' })
|
|
110
117
|
/* --- for each page path, render html using render function from ssr bundle, and inject the right css --- */
|
|
111
118
|
const pagePaths = Object.keys(pages)
|
|
@@ -144,7 +151,10 @@ export async function build({
|
|
|
144
151
|
`
|
|
145
152
|
)
|
|
146
153
|
const css = cssChunks
|
|
147
|
-
.map(
|
|
154
|
+
.map(
|
|
155
|
+
(/** @type {any} */ c) =>
|
|
156
|
+
`<link rel="stylesheet" href="/${c.fileName}">`
|
|
157
|
+
)
|
|
148
158
|
.join('\n')
|
|
149
159
|
html = html.replace(
|
|
150
160
|
'<script type="module" src="/@orga-build/main.js"></script>',
|
|
@@ -153,7 +163,7 @@ export async function build({
|
|
|
153
163
|
|
|
154
164
|
html = html.replace('</head>', `${css}</head>`)
|
|
155
165
|
|
|
156
|
-
|
|
166
|
+
const page = pages[pagePath]
|
|
157
167
|
if (page) {
|
|
158
168
|
html = html.replace(/%orga\.(\w+)%/g, (_, key) => {
|
|
159
169
|
const value = page[key] ?? ''
|
package/lib/config.d.ts
CHANGED
|
@@ -20,5 +20,9 @@ export type Config = {
|
|
|
20
20
|
* - Global stylesheet URLs injected in dev SSR and imported by client entry
|
|
21
21
|
*/
|
|
22
22
|
styles?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* - Extra rehype plugins appended to orga-build defaults
|
|
25
|
+
*/
|
|
26
|
+
rehypePlugins?: import("unified").PluggableList;
|
|
23
27
|
};
|
|
24
28
|
//# sourceMappingURL=config.d.ts.map
|
package/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["config.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["config.js"],"names":[],"mappings":"AA2BA;;;GAGG;AACH,qCAHW,MAAM,EAAE,GACN,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CA+C5D;;YAvEa,MAAM;UACN,MAAM;cACN,MAAM,EAAE;eACR,MAAM,EAAE;;;;iBACR,OAAO,MAAM,EAAE,YAAY,EAAE;oBAC7B,MAAM,EAAE,GAAC,MAAM;;;;aACf,MAAM,EAAE;;;;oBACR,OAAO,SAAS,EAAE,aAAa"}
|
package/lib/config.js
CHANGED
|
@@ -10,6 +10,7 @@ import path from 'node:path'
|
|
|
10
10
|
* @property {import('vite').PluginOption[]} vitePlugins - Array of Vite plugins
|
|
11
11
|
* @property {string[]|string} containerClass
|
|
12
12
|
* @property {string[]} [styles] - Global stylesheet URLs injected in dev SSR and imported by client entry
|
|
13
|
+
* @property {import('unified').PluggableList} [rehypePlugins] - Extra rehype plugins appended to orga-build defaults
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
16
|
/** @type {Config} */
|
|
@@ -20,7 +21,8 @@ const defaultConfig = {
|
|
|
20
21
|
postBuild: [],
|
|
21
22
|
vitePlugins: [],
|
|
22
23
|
containerClass: [],
|
|
23
|
-
styles: []
|
|
24
|
+
styles: [],
|
|
25
|
+
rehypePlugins: []
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
/**
|
|
@@ -65,7 +67,9 @@ export async function loadConfig(...files) {
|
|
|
65
67
|
result.root = resolveConfigPath(result.root)
|
|
66
68
|
result.outDir = resolveConfigPath(result.outDir)
|
|
67
69
|
const styles = result.styles
|
|
68
|
-
result.styles = Array.isArray(styles)
|
|
70
|
+
result.styles = Array.isArray(styles)
|
|
71
|
+
? styles.filter((v) => typeof v === 'string')
|
|
72
|
+
: []
|
|
69
73
|
return {
|
|
70
74
|
config: result,
|
|
71
75
|
projectRoot: configPath ? path.dirname(configPath) : cwd
|
package/lib/csr.jsx
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
1
|
import { createRoot } from 'react-dom/client'
|
|
3
|
-
import { App } from './app.jsx'
|
|
4
2
|
import { Router } from 'wouter'
|
|
3
|
+
import { App } from './app.jsx'
|
|
5
4
|
|
|
6
5
|
const container = document.getElementById('root')
|
|
7
6
|
const root = createRoot(container)
|
package/lib/files.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { globby } from 'globby'
|
|
2
|
-
import path from 'node:path'
|
|
3
1
|
import { readFile } from 'node:fs/promises'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { globby } from 'globby'
|
|
4
4
|
import { getSettings } from 'orga'
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -64,7 +64,7 @@ function getContentPath(slug) {
|
|
|
64
64
|
*/
|
|
65
65
|
function getContentId(slug) {
|
|
66
66
|
// Remove leading and trailing slashes
|
|
67
|
-
|
|
67
|
+
const normalized = slug.replace(/^\/+/, '').replace(/\/+$/, '')
|
|
68
68
|
|
|
69
69
|
// If root page, return 'index'
|
|
70
70
|
if (!normalized) {
|
package/lib/fs.js
CHANGED
package/lib/orga.d.ts
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
* @param {Object} options
|
|
3
3
|
* @param {string|string[]} options.containerClass - CSS class name(s) to wrap the rendered content
|
|
4
4
|
* @param {string} options.root - Root directory for content files
|
|
5
|
+
* @param {import('unified').PluggableList} [options.rehypePlugins] - Extra rehype plugins appended to defaults
|
|
5
6
|
*/
|
|
6
|
-
export function setupOrga({ containerClass, root }: {
|
|
7
|
+
export function setupOrga({ containerClass, root, rehypePlugins }: {
|
|
7
8
|
containerClass: string | string[];
|
|
8
9
|
root: string;
|
|
10
|
+
rehypePlugins?: import("unified").PluggableList | undefined;
|
|
9
11
|
}): import("@orgajs/rollup").Plugin;
|
|
10
12
|
//# sourceMappingURL=orga.d.ts.map
|
package/lib/orga.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orga.d.ts","sourceRoot":"","sources":["orga.js"],"names":[],"mappings":"AAQA
|
|
1
|
+
{"version":3,"file":"orga.d.ts","sourceRoot":"","sources":["orga.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,mEAJG;IAAiC,cAAc,EAAvC,MAAM,GAAC,MAAM,EAAE;IACC,IAAI,EAApB,MAAM;IACoC,aAAa;CACjE,mCAaA"}
|
package/lib/orga.js
CHANGED
|
@@ -10,13 +10,15 @@ import { getSlugFromContentFilePath } from './files.js'
|
|
|
10
10
|
* @param {Object} options
|
|
11
11
|
* @param {string|string[]} options.containerClass - CSS class name(s) to wrap the rendered content
|
|
12
12
|
* @param {string} options.root - Root directory for content files
|
|
13
|
+
* @param {import('unified').PluggableList} [options.rehypePlugins] - Extra rehype plugins appended to defaults
|
|
13
14
|
*/
|
|
14
|
-
export function setupOrga({ containerClass, root }) {
|
|
15
|
+
export function setupOrga({ containerClass, root, rehypePlugins = [] }) {
|
|
15
16
|
return _orga({
|
|
16
17
|
rehypePlugins: [
|
|
17
18
|
[rehypeWrap, { className: containerClass }],
|
|
18
19
|
[rewriteOrgFileLinks, { root }],
|
|
19
|
-
mediaAssets
|
|
20
|
+
mediaAssets,
|
|
21
|
+
...rehypePlugins
|
|
20
22
|
],
|
|
21
23
|
reorgRehypeOptions: {
|
|
22
24
|
linkHref: (link) => link.path.value
|
|
@@ -39,7 +41,8 @@ function mediaAssets() {
|
|
|
39
41
|
if (typeof src !== 'string') return
|
|
40
42
|
if (src.startsWith('http')) return
|
|
41
43
|
const tagName = node.tagName
|
|
42
|
-
|
|
44
|
+
if (!imports[src]) imports[src] = `asset_${genId()}`
|
|
45
|
+
const name = imports[src]
|
|
43
46
|
const attrs = Object.entries(rest)
|
|
44
47
|
.filter(([, v]) => v !== undefined && v !== false)
|
|
45
48
|
.map(([k, v]) => (v === true ? k : `${k}='${v}'`))
|
|
@@ -80,7 +83,7 @@ function rehypeWrap({ className = [] }) {
|
|
|
80
83
|
properties: {
|
|
81
84
|
className
|
|
82
85
|
},
|
|
83
|
-
// @ts-
|
|
86
|
+
// @ts-expect-error
|
|
84
87
|
children: tree.children
|
|
85
88
|
}
|
|
86
89
|
]
|
|
@@ -131,7 +134,10 @@ function resolveOrgHrefToContentSlug({ root, filePath, href }) {
|
|
|
131
134
|
: path.resolve(path.dirname(filePath), decodedHrefPath)
|
|
132
135
|
|
|
133
136
|
const relativeTargetPath = path.relative(root, absoluteTargetPath)
|
|
134
|
-
if (
|
|
137
|
+
if (
|
|
138
|
+
relativeTargetPath.startsWith('..') ||
|
|
139
|
+
path.isAbsolute(relativeTargetPath)
|
|
140
|
+
) {
|
|
135
141
|
return null
|
|
136
142
|
}
|
|
137
143
|
|
package/lib/plugin.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @property {string | undefined} [outDir] - Output directory (excluded from file discovery)
|
|
5
5
|
* @property {string|string[]} [containerClass] - CSS class(es) to wrap rendered content
|
|
6
6
|
* @property {string[]} [styles] - Global stylesheet URLs to import/inject
|
|
7
|
+
* @property {import('unified').PluggableList} [rehypePlugins] - Extra rehype plugins appended to orga-build defaults
|
|
7
8
|
*/
|
|
8
9
|
/**
|
|
9
10
|
* Creates the canonical orga-build plugin preset.
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
* @param {OrgaBuildPluginOptions} options
|
|
13
14
|
* @returns {import('vite').PluginOption[]}
|
|
14
15
|
*/
|
|
15
|
-
export function orgaBuildPlugin({ root, outDir, containerClass, styles }: OrgaBuildPluginOptions): import("vite").PluginOption[];
|
|
16
|
+
export function orgaBuildPlugin({ root, outDir, containerClass, styles, rehypePlugins }: OrgaBuildPluginOptions): import("vite").PluginOption[];
|
|
16
17
|
/**
|
|
17
18
|
* Creates the full Vite config options for orga-build.
|
|
18
19
|
* Includes plugins, resolve aliases, and other shared config.
|
|
@@ -20,7 +21,7 @@ export function orgaBuildPlugin({ root, outDir, containerClass, styles }: OrgaBu
|
|
|
20
21
|
* @param {OrgaBuildPluginOptions & { outDir?: string, vitePlugins?: import('vite').PluginOption[], includeFallbackHtml?: boolean, projectRoot?: string }} options
|
|
21
22
|
* @returns {{ plugins: import('vite').PluginOption[], resolve: { alias: typeof alias } }}
|
|
22
23
|
*/
|
|
23
|
-
export function createOrgaBuildConfig({ root, outDir, containerClass, styles, vitePlugins, includeFallbackHtml, projectRoot }: OrgaBuildPluginOptions & {
|
|
24
|
+
export function createOrgaBuildConfig({ root, outDir, containerClass, styles, rehypePlugins, vitePlugins, includeFallbackHtml, projectRoot }: OrgaBuildPluginOptions & {
|
|
24
25
|
outDir?: string;
|
|
25
26
|
vitePlugins?: import("vite").PluginOption[];
|
|
26
27
|
includeFallbackHtml?: boolean;
|
|
@@ -71,5 +72,9 @@ export type OrgaBuildPluginOptions = {
|
|
|
71
72
|
* - Global stylesheet URLs to import/inject
|
|
72
73
|
*/
|
|
73
74
|
styles?: string[];
|
|
75
|
+
/**
|
|
76
|
+
* - Extra rehype plugins appended to orga-build defaults
|
|
77
|
+
*/
|
|
78
|
+
rehypePlugins?: import("unified").PluggableList;
|
|
74
79
|
};
|
|
75
80
|
//# sourceMappingURL=plugin.d.ts.map
|
package/lib/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["plugin.js"],"names":[],"mappings":"AAuBA
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["plugin.js"],"names":[],"mappings":"AAuBA;;;;;;;GAOG;AAEH;;;;;;GAMG;AACH,yFAHW,sBAAsB,GACpB,OAAO,MAAM,EAAE,YAAY,EAAE,CAczC;AAED;;;;;;GAMG;AACH,8IAHW,sBAAsB,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,MAAM,EAAE,YAAY,EAAE,CAAC;IAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5I;IAAE,OAAO,EAAE,OAAO,MAAM,EAAE,YAAY,EAAE,CAAC;IAAC,OAAO,EAAE;QAAE,KAAK,EAAE,OAAO,KAAK,CAAA;KAAE,CAAA;CAAE,CAyBxF;AAiBD;;;;;;;;;;;;;GAaG;AACH,gDAJW,MAAM,WACN,MAAM,EAAE,GACN,OAAO,MAAM,EAAE,MAAM,CAmFjC;AArLD;;GAEG;AACH;;;;EAIC;;;;;UAIa,MAAM;;;;aACN,MAAM,GAAG,SAAS;;;;qBAClB,MAAM,GAAC,MAAM,EAAE;;;;aACf,MAAM,EAAE;;;;oBACR,OAAO,SAAS,EAAE,aAAa"}
|
package/lib/plugin.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
1
|
import fs from 'node:fs/promises'
|
|
3
2
|
import { createRequire } from 'node:module'
|
|
3
|
+
import path from 'node:path'
|
|
4
4
|
import { fileURLToPath } from 'node:url'
|
|
5
|
-
import { createServerModuleRunner } from 'vite'
|
|
6
5
|
import react from '@vitejs/plugin-react'
|
|
6
|
+
import { createServerModuleRunner } from 'vite'
|
|
7
7
|
import { setupOrga } from './orga.js'
|
|
8
|
-
import { pluginFactory } from './vite.js'
|
|
9
8
|
import { escapeHtml } from './util.js'
|
|
9
|
+
import { pluginFactory } from './vite.js'
|
|
10
10
|
|
|
11
11
|
const ssrEntry = fileURLToPath(new URL('./ssr.jsx', import.meta.url))
|
|
12
12
|
|
|
@@ -27,6 +27,7 @@ export const alias = {
|
|
|
27
27
|
* @property {string | undefined} [outDir] - Output directory (excluded from file discovery)
|
|
28
28
|
* @property {string|string[]} [containerClass] - CSS class(es) to wrap rendered content
|
|
29
29
|
* @property {string[]} [styles] - Global stylesheet URLs to import/inject
|
|
30
|
+
* @property {import('unified').PluggableList} [rehypePlugins] - Extra rehype plugins appended to orga-build defaults
|
|
30
31
|
*/
|
|
31
32
|
|
|
32
33
|
/**
|
|
@@ -40,10 +41,11 @@ export function orgaBuildPlugin({
|
|
|
40
41
|
root,
|
|
41
42
|
outDir,
|
|
42
43
|
containerClass = [],
|
|
43
|
-
styles = []
|
|
44
|
+
styles = [],
|
|
45
|
+
rehypePlugins = []
|
|
44
46
|
}) {
|
|
45
47
|
return [
|
|
46
|
-
setupOrga({ containerClass, root }),
|
|
48
|
+
setupOrga({ containerClass, root, rehypePlugins }),
|
|
47
49
|
react(),
|
|
48
50
|
pluginFactory({ dir: root, outDir, styles })
|
|
49
51
|
]
|
|
@@ -61,13 +63,14 @@ export function createOrgaBuildConfig({
|
|
|
61
63
|
outDir,
|
|
62
64
|
containerClass = [],
|
|
63
65
|
styles = [],
|
|
66
|
+
rehypePlugins = [],
|
|
64
67
|
vitePlugins = [],
|
|
65
68
|
includeFallbackHtml = false,
|
|
66
69
|
projectRoot = process.cwd()
|
|
67
70
|
}) {
|
|
68
71
|
const plugins = [
|
|
69
72
|
...vitePlugins,
|
|
70
|
-
...orgaBuildPlugin({ root, outDir, containerClass, styles })
|
|
73
|
+
...orgaBuildPlugin({ root, outDir, containerClass, styles, rehypePlugins })
|
|
71
74
|
]
|
|
72
75
|
if (includeFallbackHtml) {
|
|
73
76
|
// HTML fallback must be first so it can handle HTML navigation requests
|
package/lib/serve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["serve.js"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,8BAJW,OAAO,aAAa,EAAE,MAAM,SAC5B,MAAM,gBACN,MAAM,
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["serve.js"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,8BAJW,OAAO,aAAa,EAAE,MAAM,SAC5B,MAAM,gBACN,MAAM,iBAuChB"}
|
package/lib/serve.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import { createServer } from 'vite'
|
|
3
|
-
import {
|
|
3
|
+
import { alias, createOrgaBuildConfig } from './plugin.js'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Start the development server using native Vite.
|
|
@@ -15,6 +15,7 @@ export async function serve(config, port = 3000, projectRoot = process.cwd()) {
|
|
|
15
15
|
outDir: config.outDir,
|
|
16
16
|
containerClass: config.containerClass,
|
|
17
17
|
styles: config.styles ?? [],
|
|
18
|
+
rehypePlugins: config.rehypePlugins ?? [],
|
|
18
19
|
vitePlugins: config.vitePlugins,
|
|
19
20
|
includeFallbackHtml: true,
|
|
20
21
|
projectRoot
|
|
@@ -38,7 +39,7 @@ export async function serve(config, port = 3000, projectRoot = process.cwd()) {
|
|
|
38
39
|
port,
|
|
39
40
|
strictPort: false,
|
|
40
41
|
watch: {
|
|
41
|
-
ignored: [path.resolve(config.outDir)
|
|
42
|
+
ignored: [`${path.resolve(config.outDir)}/**`]
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
})
|
package/lib/ssr.jsx
CHANGED
package/lib/vite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["vite.js"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,uDALG;IAAwB,GAAG,EAAnB,MAAM;IACW,MAAM;IACJ,MAAM;CACjC,GAAU,OAAO,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["vite.js"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,uDALG;IAAwB,GAAG,EAAnB,MAAM;IACW,MAAM;IACJ,MAAM;CACjC,GAAU,OAAO,MAAM,EAAE,MAAM,CAoJjC;AA7JD,gDAAuD"}
|
package/lib/vite.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { setup } from './files.js'
|
|
2
1
|
import path from 'node:path'
|
|
2
|
+
import { setup } from './files.js'
|
|
3
3
|
|
|
4
4
|
const magicModulePrefix = '/@orga-build/'
|
|
5
|
-
const pagesModuleId = magicModulePrefix
|
|
5
|
+
const pagesModuleId = `${magicModulePrefix}pages`
|
|
6
6
|
export const appEntryId = `${magicModulePrefix}main.js`
|
|
7
7
|
const contentModuleId = 'orga-build:content'
|
|
8
|
-
const contentModuleIdResolved =
|
|
8
|
+
const contentModuleIdResolved = `\0${contentModuleId}`
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @param {Object} options
|
|
@@ -20,21 +20,11 @@ export function pluginFactory({ dir, outDir, styles = [] }) {
|
|
|
20
20
|
return {
|
|
21
21
|
name: 'vite-plugin-orga-pages',
|
|
22
22
|
enforce: 'pre',
|
|
23
|
-
config: (
|
|
23
|
+
config: (_config, _env) => ({
|
|
24
24
|
future: {
|
|
25
25
|
removePluginHookSsrArgument: 'warn',
|
|
26
26
|
removePluginHookHandleHotUpdate: 'warn',
|
|
27
27
|
removeSsrLoadModule: 'warn'
|
|
28
|
-
},
|
|
29
|
-
optimizeDeps: {
|
|
30
|
-
include: [
|
|
31
|
-
'react',
|
|
32
|
-
'react/jsx-runtime',
|
|
33
|
-
'react-dom',
|
|
34
|
-
'react-dom/client',
|
|
35
|
-
'wouter'
|
|
36
|
-
],
|
|
37
|
-
exclude: ['orga-build']
|
|
38
28
|
}
|
|
39
29
|
}),
|
|
40
30
|
|
|
@@ -50,7 +40,7 @@ export function pluginFactory({ dir, outDir, styles = [] }) {
|
|
|
50
40
|
}
|
|
51
41
|
},
|
|
52
42
|
|
|
53
|
-
async resolveId(id,
|
|
43
|
+
async resolveId(id, _importer) {
|
|
54
44
|
if (id === appEntryId) {
|
|
55
45
|
return appEntryId
|
|
56
46
|
}
|
|
@@ -75,7 +65,7 @@ export function pluginFactory({ dir, outDir, styles = [] }) {
|
|
|
75
65
|
return await renderPageList()
|
|
76
66
|
}
|
|
77
67
|
if (id.startsWith(pagesModuleId)) {
|
|
78
|
-
|
|
68
|
+
const pageId = id.replace(pagesModuleId, '')
|
|
79
69
|
const page = await files.page(pageId)
|
|
80
70
|
if (page) {
|
|
81
71
|
return `
|
|
@@ -111,7 +101,7 @@ export default layouts;
|
|
|
111
101
|
const pages = await files.pages()
|
|
112
102
|
/** @type {string[]} */ const _imports = []
|
|
113
103
|
/** @type {string[]} */ const _pages = []
|
|
114
|
-
Object.entries(pages).forEach(([pageId,
|
|
104
|
+
Object.entries(pages).forEach(([pageId, _value], i) => {
|
|
115
105
|
const dataModulePath = path.join(magicModulePrefix, 'pages', pageId)
|
|
116
106
|
_imports.push(`import * as page${i} from '${dataModulePath}'`)
|
|
117
107
|
_pages.push(`pages['${pageId}'] = page${i}`)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orga-build",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "A simple tool that builds org-mode files into a website",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -48,17 +48,18 @@
|
|
|
48
48
|
"react": "^19.0.0",
|
|
49
49
|
"react-dom": "^19.0.0",
|
|
50
50
|
"rehype-katex": "^7.0.1",
|
|
51
|
+
"unified": "^11.0.5",
|
|
51
52
|
"unist-util-visit-parents": "^6.0.1",
|
|
52
53
|
"vite": "^7.3.1",
|
|
53
54
|
"wouter": "^3.7.0",
|
|
54
|
-
"@orgajs/rollup": "1.3.
|
|
55
|
+
"@orgajs/rollup": "1.3.4"
|
|
55
56
|
},
|
|
56
57
|
"devDependencies": {
|
|
57
58
|
"@types/hast": "^3.0.4",
|
|
58
|
-
"@types/node": "^
|
|
59
|
+
"@types/node": "^25.3.2",
|
|
59
60
|
"@types/react": "^19.0.8",
|
|
60
61
|
"@types/react-dom": "^19.0.3",
|
|
61
|
-
"orga": "4.
|
|
62
|
+
"orga": "4.7.1"
|
|
62
63
|
},
|
|
63
64
|
"scripts": {
|
|
64
65
|
"clean": "fd . -e d.ts -e d.ts.map -I -x rm {}",
|