methanol 0.0.11 → 0.0.12
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 +4 -1
- package/package.json +1 -1
- package/src/build-system.js +116 -44
- package/src/config.js +13 -2
- package/src/dev-server.js +155 -24
- package/src/logger.js +15 -3
- package/src/mdx.js +68 -39
- package/src/pages.js +216 -56
- package/src/state.js +18 -14
- package/src/workers/build-pool.js +156 -0
- package/src/workers/build-worker.js +203 -0
- package/src/workers/mdx-compile-worker.js +60 -0
- package/themes/default/src/nav-tree.jsx +6 -5
package/README.md
CHANGED
|
@@ -41,9 +41,12 @@ export default () => ({
|
|
|
41
41
|
enabled: true
|
|
42
42
|
},
|
|
43
43
|
|
|
44
|
-
// optional: code highlighting (Starry Night)
|
|
44
|
+
// optional: code highlighting (Starry Night, default: enabled)
|
|
45
45
|
starryNight: false,
|
|
46
46
|
|
|
47
|
+
// optional: worker thread count (0 = auto)
|
|
48
|
+
jobs: 0,
|
|
49
|
+
|
|
47
50
|
// optional: pwa support
|
|
48
51
|
pwa: true,
|
|
49
52
|
|
package/package.json
CHANGED
package/src/build-system.js
CHANGED
|
@@ -26,8 +26,8 @@ import { VitePWA } from 'vite-plugin-pwa'
|
|
|
26
26
|
import { state, cli } from './state.js'
|
|
27
27
|
import { resolveUserViteConfig } from './config.js'
|
|
28
28
|
import { buildPagesContext } from './pages.js'
|
|
29
|
-
import { renderHtml } from './mdx.js'
|
|
30
29
|
import { buildComponentRegistry } from './components.js'
|
|
30
|
+
import { createBuildWorkers, runWorkerStage, terminateWorkers } from './workers/build-pool.js'
|
|
31
31
|
import { methanolVirtualHtmlPlugin, methanolResolverPlugin } from './vite-plugins.js'
|
|
32
32
|
import { createStageLogger } from './stage-logger.js'
|
|
33
33
|
import { preparePublicAssets } from './public-assets.js'
|
|
@@ -40,7 +40,6 @@ const ensureDir = async (dir) => {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
const isHtmlFile = (name) => name.endsWith('.html')
|
|
43
|
-
|
|
44
43
|
const collectHtmlFiles = async (dir, basePath = '') => {
|
|
45
44
|
const entries = await readdir(dir)
|
|
46
45
|
const files = []
|
|
@@ -76,22 +75,14 @@ export const buildHtmlEntries = async () => {
|
|
|
76
75
|
const stageLogger = createStageLogger(logEnabled)
|
|
77
76
|
const themeComponentsDir = state.THEME_COMPONENTS_DIR
|
|
78
77
|
const themeEnv = state.THEME_ENV
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
: { components: {} }
|
|
85
|
-
const themeComponents = {
|
|
86
|
-
...(themeRegistry.components || {}),
|
|
87
|
-
...(state.USER_THEME.components || {})
|
|
88
|
-
}
|
|
89
|
-
const { components } = await buildComponentRegistry()
|
|
90
|
-
const mergedComponents = {
|
|
91
|
-
...themeComponents,
|
|
92
|
-
...components
|
|
78
|
+
if (themeComponentsDir) {
|
|
79
|
+
await buildComponentRegistry({
|
|
80
|
+
componentsDir: themeComponentsDir,
|
|
81
|
+
client: themeEnv.client
|
|
82
|
+
})
|
|
93
83
|
}
|
|
94
|
-
|
|
84
|
+
await buildComponentRegistry()
|
|
85
|
+
const pagesContext = await buildPagesContext({ compileAll: false })
|
|
95
86
|
const entry = {}
|
|
96
87
|
const htmlCache = new Map()
|
|
97
88
|
const resolveOutputName = (page) => {
|
|
@@ -102,42 +93,123 @@ export const buildHtmlEntries = async () => {
|
|
|
102
93
|
return page.routePath.slice(1)
|
|
103
94
|
}
|
|
104
95
|
|
|
105
|
-
const
|
|
106
|
-
const totalPages =
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
96
|
+
const pages = pagesContext.pages || []
|
|
97
|
+
const totalPages = pages.length
|
|
98
|
+
const { workers, assignments } = createBuildWorkers(totalPages)
|
|
99
|
+
const excludedRoutes = Array.from(pagesContext.excludedRoutes || [])
|
|
100
|
+
const excludedDirs = Array.from(pagesContext.excludedDirs || [])
|
|
101
|
+
try {
|
|
102
|
+
await runWorkerStage({
|
|
103
|
+
workers,
|
|
104
|
+
stage: 'setPages',
|
|
105
|
+
messages: workers.map((worker) => ({
|
|
106
|
+
worker,
|
|
107
|
+
message: {
|
|
108
|
+
type: 'setPages',
|
|
109
|
+
stage: 'setPages',
|
|
110
|
+
pages,
|
|
111
|
+
excludedRoutes,
|
|
112
|
+
excludedDirs
|
|
113
|
+
}
|
|
114
|
+
}))
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
const compileToken = stageLogger.start('Compiling MDX')
|
|
118
|
+
let completed = 0
|
|
119
|
+
const updates = await runWorkerStage({
|
|
120
|
+
workers,
|
|
121
|
+
stage: 'compile',
|
|
122
|
+
messages: workers.map((worker, index) => ({
|
|
123
|
+
worker,
|
|
124
|
+
message: {
|
|
125
|
+
type: 'compile',
|
|
126
|
+
stage: 'compile',
|
|
127
|
+
ids: assignments[index]
|
|
128
|
+
}
|
|
129
|
+
})),
|
|
130
|
+
onProgress: (count) => {
|
|
131
|
+
if (!logEnabled) return
|
|
132
|
+
completed = count
|
|
133
|
+
stageLogger.update(compileToken, `Compiling MDX [${completed}/${totalPages}]`)
|
|
134
|
+
},
|
|
135
|
+
collect: (message) => message.updates || []
|
|
136
|
+
})
|
|
137
|
+
stageLogger.end(compileToken)
|
|
138
|
+
|
|
139
|
+
for (const update of updates) {
|
|
140
|
+
const page = pages[update.id]
|
|
141
|
+
if (!page) continue
|
|
142
|
+
if (update.title !== undefined) page.title = update.title
|
|
143
|
+
if (update.toc !== undefined) page.toc = update.toc
|
|
144
|
+
if (typeof pagesContext.setDerivedTitle === 'function') {
|
|
145
|
+
const shouldUseTocTitle = page.frontmatter?.title == null
|
|
146
|
+
pagesContext.setDerivedTitle(page.path, shouldUseTocTitle ? page.title : null, page.toc || null)
|
|
147
|
+
}
|
|
114
148
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
149
|
+
pagesContext.refreshPagesTree?.()
|
|
150
|
+
|
|
151
|
+
const titleSnapshot = pages.map((page) => page.title)
|
|
152
|
+
await runWorkerStage({
|
|
153
|
+
workers,
|
|
154
|
+
stage: 'sync',
|
|
155
|
+
messages: workers.map((worker) => ({
|
|
156
|
+
worker,
|
|
157
|
+
message: {
|
|
158
|
+
type: 'sync',
|
|
159
|
+
stage: 'sync',
|
|
160
|
+
updates,
|
|
161
|
+
titles: titleSnapshot
|
|
162
|
+
}
|
|
163
|
+
}))
|
|
121
164
|
})
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
165
|
+
|
|
166
|
+
const renderToken = stageLogger.start('Rendering pages')
|
|
167
|
+
completed = 0
|
|
168
|
+
const rendered = await runWorkerStage({
|
|
169
|
+
workers,
|
|
170
|
+
stage: 'render',
|
|
171
|
+
messages: workers.map((worker, index) => ({
|
|
172
|
+
worker,
|
|
173
|
+
message: {
|
|
174
|
+
type: 'render',
|
|
175
|
+
stage: 'render',
|
|
176
|
+
ids: assignments[index]
|
|
177
|
+
}
|
|
178
|
+
})),
|
|
179
|
+
onProgress: (count) => {
|
|
180
|
+
if (!logEnabled) return
|
|
181
|
+
completed = count
|
|
182
|
+
stageLogger.update(renderToken, `Rendering pages [${completed}/${totalPages}]`)
|
|
183
|
+
},
|
|
184
|
+
collect: (message) => message.results || []
|
|
185
|
+
})
|
|
186
|
+
stageLogger.end(renderToken)
|
|
187
|
+
|
|
188
|
+
for (const item of rendered) {
|
|
189
|
+
const page = pages[item.id]
|
|
190
|
+
if (!page) continue
|
|
191
|
+
const html = item.html
|
|
192
|
+
const name = resolveOutputName(page)
|
|
193
|
+
const id = normalizePath(resolve(state.VIRTUAL_HTML_OUTPUT_ROOT, `${name}.html`))
|
|
194
|
+
entry[name] = id
|
|
195
|
+
htmlCache.set(id, html)
|
|
196
|
+
if (state.INTERMEDIATE_DIR) {
|
|
197
|
+
const outPath = resolve(state.INTERMEDIATE_DIR, `${name}.html`)
|
|
198
|
+
await ensureDir(dirname(outPath))
|
|
199
|
+
await writeFile(outPath, html)
|
|
200
|
+
}
|
|
130
201
|
}
|
|
202
|
+
} finally {
|
|
203
|
+
await terminateWorkers(workers)
|
|
131
204
|
}
|
|
132
|
-
stageLogger.end(renderToken)
|
|
133
205
|
|
|
134
206
|
const htmlFiles = await collectHtmlFiles(state.PAGES_DIR)
|
|
135
|
-
const
|
|
207
|
+
const htmlExcludedDirs = pagesContext.excludedDirs || new Set()
|
|
136
208
|
const isHtmlExcluded = (relativePath) => {
|
|
137
|
-
if (!
|
|
209
|
+
if (!htmlExcludedDirs.size) return false
|
|
138
210
|
const dir = relativePath.split('/').slice(0, -1).join('/')
|
|
139
211
|
if (!dir) return false
|
|
140
|
-
for (const excludedDir of
|
|
212
|
+
for (const excludedDir of htmlExcludedDirs) {
|
|
141
213
|
if (!excludedDir) return true
|
|
142
214
|
if (dir === excludedDir || dir.startsWith(`${excludedDir}/`)) {
|
|
143
215
|
return true
|
package/src/config.js
CHANGED
|
@@ -191,12 +191,12 @@ const resolvePagefindBuild = (config) => {
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
const resolveStarryNightConfig = (value) => {
|
|
194
|
-
if (value == null) return { enabled:
|
|
194
|
+
if (value == null) return { enabled: true, options: null }
|
|
195
195
|
if (typeof value === 'boolean') {
|
|
196
196
|
return { enabled: value, options: null }
|
|
197
197
|
}
|
|
198
198
|
if (typeof value !== 'object') {
|
|
199
|
-
return { enabled:
|
|
199
|
+
return { enabled: true, options: null }
|
|
200
200
|
}
|
|
201
201
|
const { enabled, options, ...rest } = value
|
|
202
202
|
if (enabled === false) return { enabled: false, options: null }
|
|
@@ -216,6 +216,14 @@ const normalizeHooks = (value) => {
|
|
|
216
216
|
return []
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
const normalizeJobs = (value) => {
|
|
220
|
+
if (value == null) return null
|
|
221
|
+
const parsed = Number(value)
|
|
222
|
+
if (!Number.isFinite(parsed)) return null
|
|
223
|
+
if (parsed <= 0) return 0
|
|
224
|
+
return Math.floor(parsed)
|
|
225
|
+
}
|
|
226
|
+
|
|
219
227
|
const loadConfigModule = async (filePath) => {
|
|
220
228
|
return import(`${pathToFileURL(filePath).href}?t=${Date.now()}`)
|
|
221
229
|
}
|
|
@@ -425,6 +433,9 @@ export const applyConfig = async (config, mode) => {
|
|
|
425
433
|
state.STARRY_NIGHT_OPTIONS = starryNight.enabled ? starryNight.options : null
|
|
426
434
|
}
|
|
427
435
|
|
|
436
|
+
const jobsValue = cli.CLI_JOBS != null ? cli.CLI_JOBS : config.jobs
|
|
437
|
+
state.WORKER_JOBS = normalizeJobs(jobsValue) ?? 0
|
|
438
|
+
|
|
428
439
|
if (cli.CLI_INTERMEDIATE_DIR) {
|
|
429
440
|
state.INTERMEDIATE_DIR = resolveFromRoot(root, cli.CLI_INTERMEDIATE_DIR, 'build')
|
|
430
441
|
} else if (config.intermediateDir) {
|
package/src/dev-server.js
CHANGED
|
@@ -40,6 +40,8 @@ import { buildPagesContext, buildPageEntry, routePathFromFile } from './pages.js
|
|
|
40
40
|
import { compilePageMdx, renderHtml } from './mdx.js'
|
|
41
41
|
import { methanolResolverPlugin } from './vite-plugins.js'
|
|
42
42
|
import { preparePublicAssets, updateAsset } from './public-assets.js'
|
|
43
|
+
import { createBuildWorkers, runWorkerStage, terminateWorkers } from './workers/build-pool.js'
|
|
44
|
+
import { style } from './logger.js'
|
|
43
45
|
|
|
44
46
|
export const runViteDev = async () => {
|
|
45
47
|
const baseFsAllow = [state.ROOT_DIR, state.USER_THEME.root].filter(Boolean)
|
|
@@ -152,19 +154,128 @@ export const runViteDev = async () => {
|
|
|
152
154
|
htmlCache.clear()
|
|
153
155
|
}
|
|
154
156
|
|
|
157
|
+
const logMdxError = (phase, error, page = null) => {
|
|
158
|
+
const target = page?.path || page?.routePath || 'unknown file'
|
|
159
|
+
console.error(style.red(`\n[methanol] ${phase} error in ${target}`))
|
|
160
|
+
console.error(error?.stack || error)
|
|
161
|
+
}
|
|
162
|
+
|
|
155
163
|
const refreshPagesContext = async () => {
|
|
156
164
|
setPagesContext(await buildPagesContext({ compileAll: false }))
|
|
157
165
|
}
|
|
158
166
|
|
|
167
|
+
const prebuildHtmlCache = async (token) => {
|
|
168
|
+
if (!pagesContext || token !== pagesContextToken) return
|
|
169
|
+
const pages = pagesContext.pages || []
|
|
170
|
+
if (!pages.length) return
|
|
171
|
+
const { workers, assignments } = createBuildWorkers(pages.length, { command: 'serve' })
|
|
172
|
+
const excludedRoutes = Array.from(pagesContext.excludedRoutes || [])
|
|
173
|
+
const excludedDirs = Array.from(pagesContext.excludedDirs || [])
|
|
174
|
+
try {
|
|
175
|
+
await runWorkerStage({
|
|
176
|
+
workers,
|
|
177
|
+
stage: 'setPages',
|
|
178
|
+
messages: workers.map((worker) => ({
|
|
179
|
+
worker,
|
|
180
|
+
message: {
|
|
181
|
+
type: 'setPages',
|
|
182
|
+
stage: 'setPages',
|
|
183
|
+
pages,
|
|
184
|
+
excludedRoutes,
|
|
185
|
+
excludedDirs
|
|
186
|
+
}
|
|
187
|
+
}))
|
|
188
|
+
})
|
|
189
|
+
if (token !== pagesContextToken) return
|
|
190
|
+
|
|
191
|
+
const updates = await runWorkerStage({
|
|
192
|
+
workers,
|
|
193
|
+
stage: 'compile',
|
|
194
|
+
messages: workers.map((worker, index) => ({
|
|
195
|
+
worker,
|
|
196
|
+
message: {
|
|
197
|
+
type: 'compile',
|
|
198
|
+
stage: 'compile',
|
|
199
|
+
ids: assignments[index]
|
|
200
|
+
}
|
|
201
|
+
})),
|
|
202
|
+
collect: (message) => message.updates || []
|
|
203
|
+
})
|
|
204
|
+
if (token !== pagesContextToken) return
|
|
205
|
+
|
|
206
|
+
for (const update of updates) {
|
|
207
|
+
const page = pages[update.id]
|
|
208
|
+
if (!page) continue
|
|
209
|
+
if (update.title !== undefined) page.title = update.title
|
|
210
|
+
if (update.toc !== undefined) page.toc = update.toc
|
|
211
|
+
if (typeof pagesContext.setDerivedTitle === 'function') {
|
|
212
|
+
const shouldUseTocTitle = page.frontmatter?.title == null
|
|
213
|
+
pagesContext.setDerivedTitle(page.path, shouldUseTocTitle ? page.title : null, page.toc || null)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
pagesContext.refreshPagesTree?.()
|
|
217
|
+
invalidateHtmlCache()
|
|
218
|
+
const renderEpoch = htmlCacheEpoch
|
|
219
|
+
|
|
220
|
+
const titleSnapshot = pages.map((page) => page.title)
|
|
221
|
+
await runWorkerStage({
|
|
222
|
+
workers,
|
|
223
|
+
stage: 'sync',
|
|
224
|
+
messages: workers.map((worker) => ({
|
|
225
|
+
worker,
|
|
226
|
+
message: {
|
|
227
|
+
type: 'sync',
|
|
228
|
+
stage: 'sync',
|
|
229
|
+
updates,
|
|
230
|
+
titles: titleSnapshot
|
|
231
|
+
}
|
|
232
|
+
}))
|
|
233
|
+
})
|
|
234
|
+
if (token !== pagesContextToken) return
|
|
235
|
+
|
|
236
|
+
const rendered = await runWorkerStage({
|
|
237
|
+
workers,
|
|
238
|
+
stage: 'render',
|
|
239
|
+
messages: workers.map((worker, index) => ({
|
|
240
|
+
worker,
|
|
241
|
+
message: {
|
|
242
|
+
type: 'render',
|
|
243
|
+
stage: 'render',
|
|
244
|
+
ids: assignments[index]
|
|
245
|
+
}
|
|
246
|
+
})),
|
|
247
|
+
collect: (message) => message.results || []
|
|
248
|
+
})
|
|
249
|
+
if (token !== pagesContextToken || renderEpoch !== htmlCacheEpoch) return
|
|
250
|
+
for (const item of rendered) {
|
|
251
|
+
const page = pages[item.id]
|
|
252
|
+
if (!page) continue
|
|
253
|
+
htmlCache.set(page.routePath, {
|
|
254
|
+
html: item.html,
|
|
255
|
+
path: page.path,
|
|
256
|
+
epoch: renderEpoch,
|
|
257
|
+
token
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
} finally {
|
|
261
|
+
await terminateWorkers(workers)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
159
265
|
const runInitialCompile = async () => {
|
|
160
266
|
const token = pagesContextToken
|
|
161
267
|
try {
|
|
162
|
-
const nextContext = await buildPagesContext({ compileAll:
|
|
268
|
+
const nextContext = await buildPagesContext({ compileAll: false })
|
|
163
269
|
if (token !== pagesContextToken) {
|
|
164
270
|
return
|
|
165
271
|
}
|
|
166
272
|
setPagesContext(nextContext)
|
|
273
|
+
const nextToken = pagesContextToken
|
|
167
274
|
invalidateHtmlCache()
|
|
275
|
+
await prebuildHtmlCache(nextToken)
|
|
276
|
+
if (nextToken !== pagesContextToken) {
|
|
277
|
+
return
|
|
278
|
+
}
|
|
168
279
|
reload()
|
|
169
280
|
} catch (err) {
|
|
170
281
|
console.error(err)
|
|
@@ -257,10 +368,6 @@ export const runViteDev = async () => {
|
|
|
257
368
|
return next()
|
|
258
369
|
}
|
|
259
370
|
|
|
260
|
-
if (pathname.includes('.') && !pathname.endsWith('.html')) {
|
|
261
|
-
return next()
|
|
262
|
-
}
|
|
263
|
-
|
|
264
371
|
const accept = req.headers.accept || ''
|
|
265
372
|
if (!pathname.endsWith('.html') && !accept.includes('text/html')) {
|
|
266
373
|
return next()
|
|
@@ -274,6 +381,11 @@ export const runViteDev = async () => {
|
|
|
274
381
|
}
|
|
275
382
|
}
|
|
276
383
|
const requestedPath = routePath
|
|
384
|
+
if (pathname.includes('.') && !pathname.endsWith('.html')) {
|
|
385
|
+
if (!pagesContext?.pagesByRoute?.has(requestedPath)) {
|
|
386
|
+
return next()
|
|
387
|
+
}
|
|
388
|
+
}
|
|
277
389
|
const isExcludedPath = () => {
|
|
278
390
|
const excludedRoutes = pagesContext.excludedRoutes
|
|
279
391
|
if (excludedRoutes?.has(requestedPath)) return true
|
|
@@ -347,7 +459,12 @@ export const runViteDev = async () => {
|
|
|
347
459
|
try {
|
|
348
460
|
const renderEpoch = htmlCacheEpoch
|
|
349
461
|
const cacheEntry = htmlCache.get(renderRoutePath)
|
|
350
|
-
if (
|
|
462
|
+
if (
|
|
463
|
+
cacheEntry &&
|
|
464
|
+
cacheEntry.path === path &&
|
|
465
|
+
cacheEntry.epoch === htmlCacheEpoch &&
|
|
466
|
+
cacheEntry.token === pagesContextToken
|
|
467
|
+
) {
|
|
351
468
|
res.statusCode = status
|
|
352
469
|
res.setHeader('Content-Type', 'text/html')
|
|
353
470
|
res.end(cacheEntry.html)
|
|
@@ -356,28 +473,37 @@ export const runViteDev = async () => {
|
|
|
356
473
|
|
|
357
474
|
pageMeta ??= pagesContext.getPageByRoute(renderRoutePath, { path })
|
|
358
475
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
476
|
+
let html = ''
|
|
477
|
+
try {
|
|
478
|
+
html = await renderHtml({
|
|
479
|
+
routePath: renderRoutePath,
|
|
480
|
+
path,
|
|
481
|
+
components: {
|
|
482
|
+
...themeComponents,
|
|
483
|
+
...components
|
|
484
|
+
},
|
|
485
|
+
pagesContext,
|
|
486
|
+
pageMeta
|
|
487
|
+
})
|
|
488
|
+
} catch (err) {
|
|
489
|
+
logMdxError('MDX render', err, pageMeta || { path, routePath: renderRoutePath })
|
|
490
|
+
res.statusCode = 500
|
|
491
|
+
res.end('Internal Server Error')
|
|
492
|
+
return
|
|
493
|
+
}
|
|
369
494
|
if (renderEpoch === htmlCacheEpoch) {
|
|
370
495
|
htmlCache.set(renderRoutePath, {
|
|
371
496
|
html,
|
|
372
497
|
path,
|
|
373
|
-
epoch: renderEpoch
|
|
498
|
+
epoch: renderEpoch,
|
|
499
|
+
token: pagesContextToken
|
|
374
500
|
})
|
|
375
501
|
}
|
|
376
502
|
res.statusCode = status
|
|
377
503
|
res.setHeader('Content-Type', 'text/html')
|
|
378
504
|
res.end(html)
|
|
379
505
|
} catch (err) {
|
|
380
|
-
|
|
506
|
+
logMdxError('MDX render', err, pageMeta || { path, routePath: renderRoutePath })
|
|
381
507
|
res.statusCode = 500
|
|
382
508
|
res.end('Internal Server Error')
|
|
383
509
|
}
|
|
@@ -532,12 +658,17 @@ export const runViteDev = async () => {
|
|
|
532
658
|
pagesContext.refreshPagesTree?.()
|
|
533
659
|
pagesContext.refreshLanguages?.()
|
|
534
660
|
if (prevEntry.content && prevEntry.content.trim().length) {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
661
|
+
try {
|
|
662
|
+
await compilePageMdx(prevEntry, pagesContext, {
|
|
663
|
+
lazyPagesTree: true,
|
|
664
|
+
refreshPagesTree: false
|
|
665
|
+
})
|
|
666
|
+
// Avoid caching a potentially stale render; recompile on request.
|
|
667
|
+
prevEntry.mdxComponent = null
|
|
668
|
+
} catch (err) {
|
|
669
|
+
logMdxError('MDX compile', err, prevEntry)
|
|
670
|
+
prevEntry.mdxComponent = null
|
|
671
|
+
}
|
|
541
672
|
}
|
|
542
673
|
return true
|
|
543
674
|
}
|
package/src/logger.js
CHANGED
|
@@ -18,10 +18,22 @@
|
|
|
18
18
|
* under the License.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
const resolveSupportColor = (stream) => {
|
|
22
|
+
if (typeof process === 'undefined') return false
|
|
23
|
+
const env = process.env || {}
|
|
24
|
+
if (env.NO_COLOR != null) return false
|
|
25
|
+
const force = env.FORCE_COLOR
|
|
26
|
+
if (force != null) {
|
|
27
|
+
return force !== '0'
|
|
28
|
+
}
|
|
29
|
+
if (stream && stream.isTTY) return true
|
|
30
|
+
const term = env.TERM || ''
|
|
31
|
+
if (!term || term.toLowerCase() === 'dumb') return false
|
|
32
|
+
return true
|
|
33
|
+
}
|
|
34
|
+
|
|
21
35
|
const supportColor =
|
|
22
|
-
|
|
23
|
-
process.stdout &&
|
|
24
|
-
(process.stdout.isTTY || process.env.FORCE_COLOR)
|
|
36
|
+
resolveSupportColor(process.stdout) || resolveSupportColor(process.stderr)
|
|
25
37
|
|
|
26
38
|
const formatter = (open, close, replace = open) =>
|
|
27
39
|
supportColor
|