methanol 0.0.12 → 0.0.13
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.md +1 -1
- package/package.json +2 -2
- package/src/build-system.js +1 -1
- package/src/components.js +16 -18
- package/src/dev-server.js +1 -1
- package/src/mdx.js +39 -48
- package/src/reframe.js +13 -6
- package/src/stage-logger.js +2 -1
- package/src/workers/build-worker.js +29 -1
- package/themes/default/components/ThemeAccentSwitch.static.jsx +3 -3
- package/themes/default/components/ThemeColorSwitch.static.jsx +3 -3
- package/themes/default/components/pre.client.jsx +2 -2
- package/themes/default/{public → sources}/theme-prepare.js +3 -2
- package/themes/default/src/page.jsx +3 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Opinionated MDX-first static site generator powered by rEFui + Vite.
|
|
4
4
|
|
|
5
|
-
For full documentation and examples, visit [Methanol Docs](https://methanol.
|
|
5
|
+
For full documentation and examples, visit [Methanol Docs](https://methanol.sudomaker.com/).
|
|
6
6
|
|
|
7
7
|
## Quick start
|
|
8
8
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "methanol",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "Static site generator powered by rEFui and MDX",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"hast-util-is-element": "^3.0.0",
|
|
37
37
|
"json5": "^2.2.3",
|
|
38
38
|
"null-prototype-object": "^1.2.5",
|
|
39
|
-
"refui": "^0.16.
|
|
39
|
+
"refui": "^0.16.4",
|
|
40
40
|
"refurbish": "^0.1.8",
|
|
41
41
|
"rehype-slug": "^6.0.0",
|
|
42
42
|
"rehype-starry-night": "^2.2.0",
|
package/src/build-system.js
CHANGED
package/src/components.js
CHANGED
|
@@ -48,21 +48,24 @@ export const bumpComponentImportNonce = () => {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export const reframeEnv = env()
|
|
51
|
-
export const
|
|
51
|
+
export const register = reframeEnv.register
|
|
52
52
|
export const invalidateRegistryEntry = reframeEnv.invalidate
|
|
53
53
|
export const genRegistryScript = reframeEnv.genRegistryScript
|
|
54
54
|
|
|
55
|
-
const resolveComponentExport = (componentPath, ext) => {
|
|
55
|
+
const resolveComponentExport = (componentPath, exportName, ext) => {
|
|
56
56
|
const staticCandidate = `${componentPath}.static${ext}`
|
|
57
57
|
const clientCandidate = `${componentPath}.client${ext}`
|
|
58
58
|
const genericCandidate = `${componentPath}${ext}`
|
|
59
|
-
const ret = {}
|
|
59
|
+
const ret = { exportName }
|
|
60
|
+
|
|
60
61
|
if (existsSync(staticCandidate)) {
|
|
61
62
|
ret.staticPath = staticCandidate
|
|
62
63
|
}
|
|
64
|
+
|
|
63
65
|
if (existsSync(clientCandidate)) {
|
|
64
66
|
ret.clientPath = clientCandidate
|
|
65
67
|
}
|
|
68
|
+
|
|
66
69
|
if (!ret.staticPath) {
|
|
67
70
|
if (existsSync(genericCandidate)) {
|
|
68
71
|
ret.staticPath = genericCandidate
|
|
@@ -70,34 +73,29 @@ const resolveComponentExport = (componentPath, ext) => {
|
|
|
70
73
|
ret.staticPath = clientCandidate
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
|
-
return ret
|
|
74
|
-
}
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (!info.staticPath) {
|
|
79
|
-
return { component: null, hasClient: false, staticPath: null, clientPath: null }
|
|
77
|
+
if (ret.staticPath) {
|
|
78
|
+
ret.staticImportURL = `${pathToFileURL(ret.staticPath).href}?t=${componentImportNonce}`
|
|
80
79
|
}
|
|
81
80
|
|
|
82
|
-
|
|
81
|
+
return ret
|
|
82
|
+
}
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
export const buildComponentEntry = async ({ dir, exportName, ext, register: registerFn = register }) => {
|
|
85
|
+
const info = resolveComponentExport(join(dir, exportName), exportName, ext)
|
|
86
|
+
if (!info.staticPath) {
|
|
85
87
|
return { component: null, hasClient: false, staticPath: null, clientPath: null }
|
|
86
88
|
}
|
|
87
89
|
|
|
88
|
-
if (info.clientPath) {
|
|
89
|
-
component = clientFn({ ...info, staticComponent: component, exportName })
|
|
90
|
-
}
|
|
91
|
-
|
|
92
90
|
return {
|
|
93
|
-
component,
|
|
91
|
+
component: registerFn(info),
|
|
94
92
|
hasClient: Boolean(info.clientPath),
|
|
95
93
|
staticPath: info.staticPath,
|
|
96
94
|
clientPath: info.clientPath || null
|
|
97
95
|
}
|
|
98
96
|
}
|
|
99
97
|
|
|
100
|
-
export const buildComponentRegistry = async ({ componentsDir = state.COMPONENTS_DIR,
|
|
98
|
+
export const buildComponentRegistry = async ({ componentsDir = state.COMPONENTS_DIR, register: registerFn = register } = {}) => {
|
|
101
99
|
const components = {}
|
|
102
100
|
const sources = new Map()
|
|
103
101
|
|
|
@@ -130,7 +128,7 @@ export const buildComponentRegistry = async ({ componentsDir = state.COMPONENTS_
|
|
|
130
128
|
dir,
|
|
131
129
|
exportName,
|
|
132
130
|
ext: extname(entry),
|
|
133
|
-
|
|
131
|
+
register: registerFn
|
|
134
132
|
})
|
|
135
133
|
if (!component) continue
|
|
136
134
|
components[exportName] = component
|
package/src/dev-server.js
CHANGED
|
@@ -129,7 +129,7 @@ export const runViteDev = async () => {
|
|
|
129
129
|
const themeRegistry = themeComponentsDir
|
|
130
130
|
? await buildComponentRegistry({
|
|
131
131
|
componentsDir: themeComponentsDir,
|
|
132
|
-
|
|
132
|
+
register: themeEnv.register
|
|
133
133
|
})
|
|
134
134
|
: { components: {} }
|
|
135
135
|
const themeComponents = {
|
package/src/mdx.js
CHANGED
|
@@ -40,16 +40,9 @@ import { linkResolve } from './rehype-plugins/link-resolve.js'
|
|
|
40
40
|
// Workaround for Vite: it doesn't support resolving module/virtual modules in script src in dev mode
|
|
41
41
|
const resolveRewindInject = () =>
|
|
42
42
|
HTMLRenderer.rawHTML(`<script type="module" src="${withBase('/.methanol_virtual_module/inject.js')}"></script>`)
|
|
43
|
-
const RWND_FALLBACK = HTMLRenderer.rawHTML
|
|
44
|
-
if
|
|
45
|
-
|
|
46
|
-
const r = function(k,i,p) {
|
|
47
|
-
l.push([k,i,p,document.currentScript])
|
|
48
|
-
}
|
|
49
|
-
r.$$loaded = l
|
|
50
|
-
window.$$rfrm = r
|
|
51
|
-
}
|
|
52
|
-
</script>`
|
|
43
|
+
const RWND_FALLBACK = HTMLRenderer.rawHTML(
|
|
44
|
+
'<script>if(!window.$$rfrm){var l=[];var r=function(k,i,p){l.push([k,i,p,document.currentScript])};r.$$loaded=l;window.$$rfrm=r}</script>'
|
|
45
|
+
)
|
|
53
46
|
|
|
54
47
|
let cachedHeadAssets = null
|
|
55
48
|
|
|
@@ -331,6 +324,7 @@ export const compilePageMdx = async (page, pagesContext, options = {}) => {
|
|
|
331
324
|
pagesContext,
|
|
332
325
|
lazyPagesTree
|
|
333
326
|
})
|
|
327
|
+
page.mdxCtx = activeCtx
|
|
334
328
|
const mdxModule = compiled?.code
|
|
335
329
|
? await runMdxSource({
|
|
336
330
|
code: compiled.code,
|
|
@@ -373,55 +367,52 @@ export const renderHtml = async ({ routePath, path, components, pagesContext, pa
|
|
|
373
367
|
|
|
374
368
|
await compilePageMdx(pageMeta, pagesContext, { ctx })
|
|
375
369
|
|
|
370
|
+
const [Head, Outlet] = createPortal()
|
|
371
|
+
const ExtraHead = () => {
|
|
372
|
+
return [
|
|
373
|
+
resolveRewindInject(),
|
|
374
|
+
...resolveUserHeadAssets(),
|
|
375
|
+
...resolvePageHeadAssets(pageMeta),
|
|
376
|
+
Outlet(),
|
|
377
|
+
RWND_FALLBACK
|
|
378
|
+
]
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const PageContent = ({ components: extraComponents, ...props }, ...children) =>
|
|
382
|
+
mdxComponent({
|
|
383
|
+
children,
|
|
384
|
+
...props,
|
|
385
|
+
components: {
|
|
386
|
+
...components,
|
|
387
|
+
...extraComponents,
|
|
388
|
+
head: Head,
|
|
389
|
+
Head
|
|
390
|
+
}
|
|
391
|
+
})
|
|
392
|
+
|
|
376
393
|
const template = state.USER_THEME.template
|
|
377
394
|
const mdxComponent = pageMeta.mdxComponent
|
|
378
395
|
|
|
379
396
|
const renderResult = await new Promise((resolve, reject) => {
|
|
380
|
-
const [Head, Outlet] = createPortal()
|
|
381
|
-
const ExtraHead = () => {
|
|
382
|
-
return [
|
|
383
|
-
resolveRewindInject(),
|
|
384
|
-
...resolveUserHeadAssets(),
|
|
385
|
-
...resolvePageHeadAssets(pageMeta),
|
|
386
|
-
Outlet(),
|
|
387
|
-
RWND_FALLBACK
|
|
388
|
-
]
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
const PageContent = ({ components: extraComponents, ...props }, ...children) => {
|
|
392
|
-
try {
|
|
393
|
-
return mdxComponent({
|
|
394
|
-
children,
|
|
395
|
-
...props,
|
|
396
|
-
components: {
|
|
397
|
-
...components,
|
|
398
|
-
...extraComponents,
|
|
399
|
-
head: Head,
|
|
400
|
-
Head
|
|
401
|
-
}
|
|
402
|
-
})
|
|
403
|
-
} catch (e) {
|
|
404
|
-
reject(e)
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
397
|
const result = HTMLRenderer.c(
|
|
409
398
|
Suspense,
|
|
410
399
|
{
|
|
411
400
|
onLoad() {
|
|
412
401
|
nextTick(() => resolve(result))
|
|
402
|
+
},
|
|
403
|
+
catch({ error }) {
|
|
404
|
+
reject(error)
|
|
413
405
|
}
|
|
414
406
|
},
|
|
415
|
-
(
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
})
|
|
407
|
+
template({
|
|
408
|
+
ctx,
|
|
409
|
+
page: ctx.page,
|
|
410
|
+
withBase,
|
|
411
|
+
PageContent,
|
|
412
|
+
ExtraHead,
|
|
413
|
+
HTMLRenderer,
|
|
414
|
+
components
|
|
415
|
+
})
|
|
425
416
|
)
|
|
426
417
|
})
|
|
427
418
|
|
package/src/reframe.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* under the License.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import { lazy } from 'refui'
|
|
21
22
|
import fnv1a from '@sindresorhus/fnv1a'
|
|
22
23
|
import JSON5 from 'json5'
|
|
23
24
|
|
|
@@ -45,8 +46,12 @@ export function env(parentEnv) {
|
|
|
45
46
|
|
|
46
47
|
let renderCount = 0
|
|
47
48
|
|
|
48
|
-
function
|
|
49
|
-
const { clientPath,
|
|
49
|
+
function register(info) {
|
|
50
|
+
const { clientPath, staticPath, staticImportURL, exportName } = info
|
|
51
|
+
|
|
52
|
+
if (!clientPath) {
|
|
53
|
+
return lazy(() => import(staticImportURL))
|
|
54
|
+
}
|
|
50
55
|
|
|
51
56
|
let key = null
|
|
52
57
|
let _clientPath = clientPath
|
|
@@ -55,7 +60,9 @@ export function env(parentEnv) {
|
|
|
55
60
|
key = hash(_clientPath)
|
|
56
61
|
} while (keyPathRegistry[key] && keyPathRegistry[key] !== clientPath)
|
|
57
62
|
|
|
58
|
-
const component = ({ children: childrenProp, ...props }, ...children) => {
|
|
63
|
+
const component = async ({ children: childrenProp, ...props }, ...children) => {
|
|
64
|
+
const staticComponent = (await import(staticImportURL)).default
|
|
65
|
+
|
|
59
66
|
const id = renderCount++
|
|
60
67
|
const idStr = id.toString(16)
|
|
61
68
|
const script = `$$rfrm(${JSON.stringify(key)},${id},${Object.keys(props).length ? JSON5.stringify(props) : '{}'})`
|
|
@@ -63,13 +70,13 @@ export function env(parentEnv) {
|
|
|
63
70
|
return (R) => {
|
|
64
71
|
return [
|
|
65
72
|
R.createAnchor(`{${idStr}}`, true),
|
|
66
|
-
R.c(
|
|
73
|
+
staticComponent ? R.c(
|
|
67
74
|
staticComponent,
|
|
68
75
|
props,
|
|
69
76
|
R.createAnchor(`[${idStr}[`, true),
|
|
70
77
|
...children,
|
|
71
78
|
R.createAnchor(`]${idStr}]`, true)
|
|
72
|
-
),
|
|
79
|
+
): null,
|
|
73
80
|
R.c('script', null, R.rawHTML(script))
|
|
74
81
|
]
|
|
75
82
|
}
|
|
@@ -106,7 +113,7 @@ export function env(parentEnv) {
|
|
|
106
113
|
}
|
|
107
114
|
|
|
108
115
|
return {
|
|
109
|
-
|
|
116
|
+
register,
|
|
110
117
|
invalidate,
|
|
111
118
|
genRegistryScript,
|
|
112
119
|
setParent,
|
package/src/stage-logger.js
CHANGED
|
@@ -41,7 +41,8 @@ export const createStageLogger = (enabled) => {
|
|
|
41
41
|
}
|
|
42
42
|
const padding = lastLength > text.length ? ' '.repeat(lastLength - text.length) : ''
|
|
43
43
|
const clearLine = '\u001b[2K'
|
|
44
|
-
|
|
44
|
+
const reset = '\x1b[0m'
|
|
45
|
+
process.stdout.write(`${clearLine}\r${reset}${text}${reset}${padding}${newline ? '\n' : ''}`)
|
|
45
46
|
lastLength = text.length
|
|
46
47
|
}
|
|
47
48
|
const start = (label) => {
|
|
@@ -46,7 +46,7 @@ const ensureInit = async () => {
|
|
|
46
46
|
const themeRegistry = themeComponentsDir
|
|
47
47
|
? await buildComponentRegistry({
|
|
48
48
|
componentsDir: themeComponentsDir,
|
|
49
|
-
|
|
49
|
+
register: themeEnv.register
|
|
50
50
|
})
|
|
51
51
|
: { components: {} }
|
|
52
52
|
const themeComponents = {
|
|
@@ -71,6 +71,30 @@ const rebuildPagesContext = async (excludedRoutes, excludedDirs) => {
|
|
|
71
71
|
})
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
const refreshMdxCtx = (page) => {
|
|
75
|
+
if (!page?.mdxCtx || !pagesContext) return
|
|
76
|
+
const ctx = page.mdxCtx
|
|
77
|
+
ctx.page = page
|
|
78
|
+
ctx.pages = pagesContext.pages || []
|
|
79
|
+
ctx.pagesByRoute = pagesContext.pagesByRoute || new Map()
|
|
80
|
+
ctx.languages = pagesContext.languages || []
|
|
81
|
+
ctx.language = pagesContext.getLanguageForRoute
|
|
82
|
+
? pagesContext.getLanguageForRoute(page.routePath)
|
|
83
|
+
: null
|
|
84
|
+
ctx.site = pagesContext.site || null
|
|
85
|
+
ctx.getSiblings = pagesContext.getSiblings
|
|
86
|
+
? () => pagesContext.getSiblings(page.routePath, page.path)
|
|
87
|
+
: null
|
|
88
|
+
if (page && ctx.getSiblings && page.getSiblings !== ctx.getSiblings) {
|
|
89
|
+
page.getSiblings = ctx.getSiblings
|
|
90
|
+
}
|
|
91
|
+
if (pagesContext.getPagesTree) {
|
|
92
|
+
ctx.pagesTree = pagesContext.getPagesTree(page.routePath)
|
|
93
|
+
} else {
|
|
94
|
+
ctx.pagesTree = pagesContext.pagesTree || []
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
74
98
|
const serializeError = (error) => {
|
|
75
99
|
if (!error) return 'Unknown error'
|
|
76
100
|
if (error.stack) return error.stack
|
|
@@ -112,6 +136,10 @@ const handleSyncUpdates = async (message) => {
|
|
|
112
136
|
excludedRoutes ? new Set(excludedRoutes) : pagesContext?.excludedRoutes || new Set(),
|
|
113
137
|
excludedDirs ? new Set(excludedDirs) : pagesContext?.excludedDirs || new Set()
|
|
114
138
|
)
|
|
139
|
+
for (const page of pages) {
|
|
140
|
+
if (!page?.mdxCtx) continue
|
|
141
|
+
refreshMdxCtx(page)
|
|
142
|
+
}
|
|
115
143
|
}
|
|
116
144
|
|
|
117
145
|
const handleCompile = async (message) => {
|
|
@@ -18,6 +18,6 @@
|
|
|
18
18
|
* under the License.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
// Nothing needs to be rendered on the server side for accent switch
|
|
22
|
+
// But we explicitly need to keep a file here to prevent Methanol from
|
|
23
|
+
// rendering the client version as fallback
|
|
@@ -18,6 +18,6 @@
|
|
|
18
18
|
* under the License.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
// Nothing needs to be rendered on the server side for accent switch
|
|
22
|
+
// But we explicitly need to keep a file here to prevent Methanol from
|
|
23
|
+
// rendering the client version as fallback
|
|
@@ -38,7 +38,7 @@ export default function (props, ...children) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const
|
|
41
|
+
const BtnImg = copied.choose(
|
|
42
42
|
() => (
|
|
43
43
|
<svg
|
|
44
44
|
attr:width="14"
|
|
@@ -74,7 +74,7 @@ export default function (props, ...children) {
|
|
|
74
74
|
return (
|
|
75
75
|
<div class="code-block-container">
|
|
76
76
|
<button class="copy-btn" on:click={copy} attr:aria-label="Copy code">
|
|
77
|
-
<
|
|
77
|
+
<BtnImg />
|
|
78
78
|
</button>
|
|
79
79
|
<pre {...props} $ref={el}>
|
|
80
80
|
{...children}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
if (savedAccent && savedAccent !== 'default') {
|
|
30
30
|
document.documentElement.classList.add('accent-' + savedAccent)
|
|
31
31
|
}
|
|
32
|
-
})
|
|
32
|
+
})
|
|
33
33
|
;(function initPrefetch() {
|
|
34
34
|
const prefetched = new Set()
|
|
35
35
|
const canPrefetch = (anchor) => {
|
|
@@ -58,4 +58,5 @@
|
|
|
58
58
|
document.head.appendChild(link)
|
|
59
59
|
}
|
|
60
60
|
document.addEventListener('pointerover', onHover, { capture: true, passive: true })
|
|
61
|
-
})
|
|
61
|
+
})
|
|
62
|
+
console.log('theme prep')
|
|
@@ -22,7 +22,7 @@ import { HTMLRenderer as R, DOCTYPE_HTML } from 'methanol'
|
|
|
22
22
|
import { renderToc } from '../components/ThemeToCContainer.static.jsx'
|
|
23
23
|
import { renderNavTree } from './nav-tree.jsx'
|
|
24
24
|
|
|
25
|
-
const PAGE_TEMPLATE =
|
|
25
|
+
const PAGE_TEMPLATE = ({ PageContent, ExtraHead, components, ctx }) => {
|
|
26
26
|
const page = ctx.page
|
|
27
27
|
const pagesByRoute = ctx.pagesByRoute
|
|
28
28
|
const pages = ctx.pages || []
|
|
@@ -122,13 +122,13 @@ const PAGE_TEMPLATE = async ({ PageContent, ExtraHead, components, ctx }) => {
|
|
|
122
122
|
{twitterTitle ? <meta name="twitter:title" content={twitterTitle} /> : null}
|
|
123
123
|
{twitterDescription ? <meta name="twitter:description" content={twitterDescription} /> : null}
|
|
124
124
|
{twitterImage ? <meta name="twitter:image" content={twitterImage} /> : null}
|
|
125
|
-
<ExtraHead />
|
|
126
125
|
<link
|
|
127
126
|
rel="preload stylesheet"
|
|
128
127
|
as="style"
|
|
129
128
|
href="/.methanol_theme_default/style.css"
|
|
130
129
|
/>
|
|
131
|
-
<script src="/theme-prepare.js"></script>
|
|
130
|
+
<script type="module" src="/.methanol_theme_default/theme-prepare.js"></script>
|
|
131
|
+
<ExtraHead />
|
|
132
132
|
</head>
|
|
133
133
|
<body>
|
|
134
134
|
<input type="checkbox" id="nav-toggle" class="nav-toggle" />
|