methanol 0.0.8 → 0.0.10

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/src/main.js CHANGED
@@ -26,6 +26,7 @@ import { runVitePreview } from './preview-server.js'
26
26
  import { cli, state } from './state.js'
27
27
  import { HTMLRenderer } from './renderer.js'
28
28
  import { readFile } from 'fs/promises'
29
+ import { style, logger } from './logger.js'
29
30
 
30
31
  const printBanner = async () => {
31
32
  try {
@@ -107,6 +108,7 @@ const main = async () => {
107
108
  return
108
109
  }
109
110
  if (isBuild) {
111
+ const startTime = performance.now()
110
112
  await runHooks(state.USER_PRE_BUILD_HOOKS)
111
113
  await runHooks(state.THEME_PRE_BUILD_HOOKS)
112
114
  const { entry, htmlCache, pagesContext } = await buildHtmlEntries()
@@ -129,6 +131,15 @@ const main = async () => {
129
131
  }
130
132
  await runHooks(state.THEME_POST_BUILD_HOOKS, buildContext)
131
133
  await runHooks(state.USER_POST_BUILD_HOOKS, buildContext)
134
+ const endTime = performance.now()
135
+ const duration = endTime - startTime
136
+ const timeString = duration > 1000 ? `${(duration / 1000).toFixed(2)}s` : `${Math.round(duration)}ms`
137
+ const totalPages = pagesContext?.pages?.length ?? 0
138
+ const pageLabel = totalPages === 1 ? 'page' : 'pages'
139
+ console.log()
140
+ logger.success(
141
+ `Build complete! Processed ${style.bold(totalPages)} ${pageLabel} in ${style.bold(timeString)}.`
142
+ )
132
143
  return
133
144
  }
134
145
  cli.showHelp()
package/src/mdx.js CHANGED
@@ -25,6 +25,7 @@ import rehypeSlug from 'rehype-slug'
25
25
  import extractToc from '@stefanprobst/rehype-extract-toc'
26
26
  import withTocExport from '@stefanprobst/rehype-extract-toc/mdx'
27
27
  import rehypeStarryNight from 'rehype-starry-night'
28
+ import remarkGfm from 'remark-gfm'
28
29
  import { HTMLRenderer } from './renderer.js'
29
30
  import { signal, computed, read, Suspense, nextTick } from 'refui'
30
31
  import { createPortal } from 'refui/extras'
@@ -40,13 +41,13 @@ import { linkResolve } from './rehype-plugins/link-resolve.js'
40
41
  const resolveRewindInject = () =>
41
42
  HTMLRenderer.rawHTML(`<script type="module" src="${withBase('/.methanol_virtual_module/inject.js')}"></script>`)
42
43
  const RWND_FALLBACK = HTMLRenderer.rawHTML`<script>
43
- if (!window.$$rwnd) {
44
+ if (!window.$$rfrm) {
44
45
  const l = []
45
46
  const r = function(k,i,p) {
46
47
  l.push([k,i,p,document.currentScript])
47
48
  }
48
49
  r.$$loaded = l
49
- window.$$rwnd = r
50
+ window.$$rfrm = r
50
51
  }
51
52
  </script>`
52
53
 
@@ -73,25 +74,21 @@ const resolveUserHeadAssets = () => {
73
74
  return assets
74
75
  }
75
76
 
76
- const resolvePageAssetUrl = (page, filePath) => {
77
- const root = page.source === 'theme' && state.THEME_PAGES_DIR
78
- ? state.THEME_PAGES_DIR
79
- : state.PAGES_DIR
77
+ const resolvePageAssetUrl = (page, path) => {
78
+ const root = page.source === 'theme' && state.THEME_PAGES_DIR ? state.THEME_PAGES_DIR : state.PAGES_DIR
80
79
  if (!root) return null
81
- const relPath = relative(root, filePath).replace(/\\/g, '/')
80
+ const relPath = relative(root, path).replace(/\\/g, '/')
82
81
  if (!relPath || relPath.startsWith('..')) return null
83
82
  return withBase(`/${relPath}`)
84
83
  }
85
84
 
86
85
  const resolvePageHeadAssets = (page) => {
87
- if (!page.filePath) return []
88
- const baseDir = dirname(page.filePath)
89
- const baseName = basename(page.filePath).replace(/\.(mdx|md)$/, '')
86
+ if (!page.path) return []
87
+ const baseDir = dirname(page.path)
88
+ const baseName = basename(page.path).replace(/\.(mdx|md)$/, '')
90
89
  const pagesRoot = state.PAGES_DIR ? resolve(state.PAGES_DIR) : null
91
- const isRootIndex =
92
- pagesRoot && baseName === 'index' && resolve(baseDir) === pagesRoot && page.source !== 'theme'
93
- const isRootStylePage =
94
- pagesRoot && baseName === 'style' && resolve(baseDir) === pagesRoot && page.source !== 'theme'
90
+ const isRootIndex = pagesRoot && baseName === 'index' && resolve(baseDir) === pagesRoot && page.source !== 'theme'
91
+ const isRootStylePage = pagesRoot && baseName === 'style' && resolve(baseDir) === pagesRoot && page.source !== 'theme'
95
92
  const assets = []
96
93
  const cssPath = resolve(baseDir, `${baseName}.css`)
97
94
  if (existsSync(cssPath)) {
@@ -131,17 +128,11 @@ const resolvePageHeadAssets = (page) => {
131
128
  return assets
132
129
  }
133
130
 
134
- export const buildPageContext = ({
135
- routePath,
136
- filePath,
137
- pageMeta,
138
- pagesContext,
139
- lazyPagesTree = false
140
- }) => {
131
+ export const buildPageContext = ({ routePath, path, pageMeta, pagesContext, lazyPagesTree = false }) => {
141
132
  const page = pageMeta
142
133
  const language = pagesContext.getLanguageForRoute ? pagesContext.getLanguageForRoute(routePath) : null
143
134
  const getSiblings = pagesContext.getSiblings
144
- ? () => pagesContext.getSiblings(routePath, page.filePath || filePath)
135
+ ? () => pagesContext.getSiblings(routePath, page.path || path)
145
136
  : null
146
137
  if (page && getSiblings && page.getSiblings !== getSiblings) {
147
138
  page.getSiblings = getSiblings
@@ -149,7 +140,7 @@ export const buildPageContext = ({
149
140
  const ctx = {
150
141
  routePath,
151
142
  routeHref: withBase(routePath),
152
- filePath,
143
+ path,
153
144
  page,
154
145
  pages: pagesContext.pages || [],
155
146
  pagesByRoute: pagesContext.pagesByRoute || new Map(),
@@ -260,11 +251,21 @@ const resolveBaseMdxConfig = async () => {
260
251
  jsxImportSource: 'refui',
261
252
  development: state.CURRENT_MODE !== 'production',
262
253
  elementAttributeNameCase: 'html',
263
- rehypePlugins: [rehypeSlug, extractToc, [withTocExport, { name: 'toc' }]]
254
+ rehypePlugins: [rehypeSlug, extractToc, [withTocExport, { name: 'toc' }]],
255
+ remarkPlugins: []
264
256
  }
257
+
258
+ if (state.GFM_ENABLED) {
259
+ baseMdxConfig.remarkPlugins.push(remarkGfm)
260
+ }
261
+
265
262
  const mdxConfig = { ...baseMdxConfig, ...userMdxConfig }
266
263
  const userRehypePlugins = Array.isArray(userMdxConfig.rehypePlugins) ? userMdxConfig.rehypePlugins : []
267
264
  mdxConfig.rehypePlugins = [...baseMdxConfig.rehypePlugins, ...userRehypePlugins]
265
+
266
+ const userRemarkPlugins = Array.isArray(userMdxConfig.remarkPlugins) ? userMdxConfig.remarkPlugins : []
267
+ mdxConfig.remarkPlugins = [...baseMdxConfig.remarkPlugins, ...userRemarkPlugins]
268
+
268
269
  mdxConfig.rehypePlugins.push(linkResolve)
269
270
  mdxConfig.rehypePlugins.push(methanolCtx)
270
271
  return (cachedMdxConfig = mdxConfig)
@@ -288,14 +289,14 @@ const resolveMdxConfigForPage = async (frontmatter) => {
288
289
  return mdxConfig
289
290
  }
290
291
 
291
- export const compileMdx = async ({ content, filePath, ctx }) => {
292
+ export const compileMdx = async ({ content, path, ctx }) => {
292
293
  const mdxConfig = await resolveMdxConfigForPage(ctx.page.frontmatter)
293
294
  const runtimeFactory = mdxConfig.development ? JSXDevFactory : JSXFactory
294
- const compiled = await compile({ value: content, path: filePath }, mdxConfig)
295
+ const compiled = await compile({ value: content, path: path }, mdxConfig)
295
296
 
296
297
  return await run(compiled, {
297
298
  ...runtimeFactory,
298
- baseUrl: pathToFileURL(filePath).href,
299
+ baseUrl: pathToFileURL(path).href,
299
300
  ctx,
300
301
  rawHTML: HTMLRenderer.rawHTML
301
302
  })
@@ -308,14 +309,14 @@ export const compilePageMdx = async (page, pagesContext, options = {}) => {
308
309
  ctx ||
309
310
  buildPageContext({
310
311
  routePath: page.routePath,
311
- filePath: page.filePath,
312
+ path: page.path,
312
313
  pageMeta: page,
313
314
  pagesContext,
314
315
  lazyPagesTree
315
316
  })
316
317
  const mdxModule = await compileMdx({
317
318
  content: page.content,
318
- filePath: page.filePath,
319
+ path: page.path,
319
320
  ctx: activeCtx
320
321
  })
321
322
  page.mdxComponent = mdxModule.default
@@ -331,23 +332,17 @@ export const compilePageMdx = async (page, pagesContext, options = {}) => {
331
332
  }
332
333
  }
333
334
  if (typeof pagesContext.setDerivedTitle === 'function') {
334
- pagesContext.setDerivedTitle(page.filePath, shouldUseTocTitle ? page.title : null, page.toc)
335
+ pagesContext.setDerivedTitle(page.path, shouldUseTocTitle ? page.title : null, page.toc)
335
336
  }
336
337
  if (ctx && refreshPagesTree && pagesContext.getPagesTree) {
337
338
  ctx.pagesTree = pagesContext.getPagesTree(activeCtx.routePath)
338
339
  }
339
340
  }
340
341
 
341
- export const renderHtml = async ({
342
- routePath,
343
- filePath,
344
- components,
345
- pagesContext,
346
- pageMeta
347
- }) => {
342
+ export const renderHtml = async ({ routePath, path, components, pagesContext, pageMeta }) => {
348
343
  const ctx = buildPageContext({
349
344
  routePath,
350
- filePath,
345
+ path,
351
346
  pageMeta,
352
347
  pagesContext
353
348
  })
package/src/pagefind.js CHANGED
@@ -22,7 +22,9 @@ import { access } from 'fs/promises'
22
22
  import { constants } from 'fs'
23
23
  import { join, delimiter } from 'path'
24
24
  import { spawn } from 'child_process'
25
- import { state } from './state.js'
25
+ import { state, cli } from './state.js'
26
+ import { createStageLogger } from './stage-logger.js'
27
+ import { logger } from './logger.js'
26
28
 
27
29
  const resolvePagefindBin = async () => {
28
30
  const binName = process.platform === 'win32' ? 'pagefind.cmd' : 'pagefind'
@@ -92,16 +94,25 @@ const runCommand = (command, args, options) =>
92
94
  export const runPagefind = async () => {
93
95
  const bin = await resolvePagefindBin()
94
96
  if (!bin) {
95
- console.log('Pagefind not found; skipping search indexing.')
97
+ logger.warn('Pagefind not found; skipping search indexing.')
96
98
  return false
97
99
  }
98
- console.log('Running Pagefind search indexing...')
100
+ const logEnabled = state.CURRENT_MODE === 'production' && cli.command === 'build' && !cli.CLI_VERBOSE
101
+ const stageLogger = createStageLogger(logEnabled)
102
+ const token = stageLogger.start('Indexing search')
103
+
104
+ if (cli.CLI_VERBOSE) {
105
+ logger.info('Running Pagefind search indexing...')
106
+ }
107
+
99
108
  const extraArgs = buildArgsFromOptions(state.PAGEFIND_BUILD)
100
109
  const ok = await runCommand(bin, ['--site', state.DIST_DIR, ...extraArgs], {
101
- cwd: state.PROJECT_ROOT
110
+ cwd: state.PROJECT_ROOT,
111
+ stdio: cli.CLI_VERBOSE ? 'inherit' : 'ignore'
102
112
  })
103
113
  if (!ok) {
104
- console.warn('Pagefind failed to build search index.')
114
+ logger.warn('Pagefind failed to build search index.')
105
115
  }
116
+ stageLogger.end(token)
106
117
  return ok
107
118
  }
package/src/pages.js CHANGED
@@ -28,7 +28,6 @@ import { compilePageMdx } from './mdx.js'
28
28
  import { createStageLogger } from './stage-logger.js'
29
29
 
30
30
  const isPageFile = (name) => name.endsWith('.mdx') || name.endsWith('.md')
31
- const isInternalPage = (name) => name.startsWith('_') || name.startsWith('.')
32
31
  const isIgnoredEntry = (name) => name.startsWith('.') || name.startsWith('_')
33
32
 
34
33
  const pageMetadataCache = new Map()
@@ -107,17 +106,17 @@ const resolveLanguageForRoute = (languages = [], routePath = '/') => {
107
106
  return best || rootLanguage
108
107
  }
109
108
 
110
- export const routePathFromFile = (filePath, pagesDir = state.PAGES_DIR) => {
111
- if (!filePath.endsWith('.mdx') && !filePath.endsWith('.md')) {
109
+ export const routePathFromFile = (path, pagesDir = state.PAGES_DIR) => {
110
+ if (!path.endsWith('.mdx') && !path.endsWith('.md')) {
112
111
  return null
113
112
  }
114
- const relPath = relative(pagesDir, filePath)
113
+ const relPath = relative(pagesDir, path)
115
114
  if (relPath.startsWith('..')) {
116
115
  return null
117
116
  }
118
117
  const name = relPath.replace(/\.(mdx|md)$/, '')
119
118
  const baseName = name.split(/[\\/]/).pop()
120
- if (isInternalPage(baseName)) {
119
+ if (isIgnoredEntry(baseName)) {
121
120
  return null
122
121
  }
123
122
  const normalized = name.replace(/\\/g, '/')
@@ -147,8 +146,8 @@ const parseFrontmatter = (raw) => {
147
146
  }
148
147
  }
149
148
 
150
- const parsePageMetadata = async (filePath) => {
151
- const raw = await readFile(filePath, 'utf-8')
149
+ const parsePageMetadata = async (path) => {
150
+ const raw = await readFile(path, 'utf-8')
152
151
  const { data: frontmatter, content, matter } = parseFrontmatter(raw)
153
152
  let title = frontmatter.title
154
153
  return {
@@ -198,13 +197,17 @@ const buildPagesTree = (pages, options = {}) => {
198
197
  }
199
198
  return routePath
200
199
  }
200
+ const buildDirRoutePath = (dir) => {
201
+ const localPath = dir ? `/${dir}/` : '/'
202
+ if (!rootPrefix) return normalizeRoutePath(localPath)
203
+ return normalizeRoutePath(`${rootPrefix}${localPath}`)
204
+ }
201
205
  const currentRouteWithinRoot = resolveRouteWithinRoot(currentRoutePath)
202
206
  const isUnderRoot = (page) => {
203
207
  if (!rootDir) return true
204
208
  return page.routePath === rootPath || (rootPrefix && page.routePath.startsWith(`${rootPrefix}/`))
205
209
  }
206
210
  const treePages = pages
207
- .filter((page) => !page.isInternal)
208
211
  .filter((page) => isUnderRoot(page))
209
212
  .map((page) => {
210
213
  if (!rootDir) return page
@@ -267,10 +270,10 @@ const buildPagesTree = (pages, options = {}) => {
267
270
  const dir = {
268
271
  type: 'directory',
269
272
  name,
270
- path: `/${path}`,
273
+ path: resolve(state.PAGES_DIR, path),
271
274
  children: [],
272
275
  depth,
273
- routePath: null,
276
+ routePath: buildDirRoutePath(path),
274
277
  routeHref: null,
275
278
  title: null,
276
279
  weight: null,
@@ -291,9 +294,9 @@ const buildPagesTree = (pages, options = {}) => {
291
294
  }
292
295
  for (const page of treePages) {
293
296
  if (page.hidden && !(includeHiddenRoot && page.routePath === rootPath)) {
294
- const isHidden404 = page.routePath === '/404'
297
+ const isHiddenSpecial = page.routePath === '/404' || page.routePath === '/offline'
295
298
  const shouldExposeHidden =
296
- !isHidden404 &&
299
+ !isHiddenSpecial &&
297
300
  page.hiddenByFrontmatter === true &&
298
301
  (
299
302
  page.routePath === currentRoutePath ||
@@ -404,7 +407,7 @@ const walkPages = async function* (dir, basePath = '') {
404
407
  const relativePath = join(basePath, name).replace(/\\/g, '/')
405
408
  const isIndex = name === 'index'
406
409
  const routePath = isIndex ? (basePath ? `/${basePath}/` : '/') : `/${relativePath}`
407
- yield { routePath, filePath: fullPath, isIndex }
410
+ yield { routePath, path: fullPath, isIndex }
408
411
  }
409
412
 
410
413
  for (const { entry, fullPath } of dirs) {
@@ -412,39 +415,45 @@ const walkPages = async function* (dir, basePath = '') {
412
415
  }
413
416
  }
414
417
 
415
- export const buildPageEntry = async ({ filePath, pagesDir, source }) => {
416
- const routePath = routePathFromFile(filePath, pagesDir)
418
+ export const buildPageEntry = async ({ path, pagesDir, source }) => {
419
+ const routePath = routePathFromFile(path, pagesDir)
417
420
  if (!routePath) return null
418
- const relPath = relative(pagesDir, filePath).replace(/\\/g, '/')
421
+ const relPath = relative(pagesDir, path).replace(/\\/g, '/')
419
422
  const name = relPath.replace(/\.(mdx|md)$/, '')
420
423
  const baseName = name.split('/').pop()
421
424
  const dir = name.split('/').slice(0, -1).join('/')
422
425
  const dirName = dir ? dir.split('/').pop() : ''
423
426
  const isIndex = baseName === 'index'
424
427
  const segments = routePath.split('/').filter(Boolean)
425
- const stats = await stat(filePath)
426
- const cached = pageMetadataCache.get(filePath)
428
+ const stats = await stat(path)
429
+ const cached = pageMetadataCache.get(path)
427
430
  let metadata = null
428
431
  if (cached && cached.mtimeMs === stats.mtimeMs) {
429
432
  metadata = cached.metadata
430
433
  } else {
431
- metadata = await parsePageMetadata(filePath)
432
- pageMetadataCache.set(filePath, { mtimeMs: stats.mtimeMs, metadata })
434
+ metadata = await parsePageMetadata(path)
435
+ pageMetadataCache.set(path, { mtimeMs: stats.mtimeMs, metadata })
433
436
  }
434
- const derived = pageDerivedCache.get(filePath)
437
+ const derived = pageDerivedCache.get(path)
435
438
  const exclude = Boolean(metadata.frontmatter?.exclude)
436
439
  const frontmatterHidden = metadata.frontmatter?.hidden
437
440
  const hiddenByFrontmatter = frontmatterHidden === true
438
441
  const isNotFoundPage = routePath === '/404'
439
- const hidden = frontmatterHidden === false
440
- ? false
441
- : frontmatterHidden === true
442
- ? true
443
- : isNotFoundPage || Boolean(metadata.frontmatter?.isRoot)
442
+ const isOfflinePage = routePath === '/offline'
443
+ const isSpecialPage = isNotFoundPage || isOfflinePage
444
+ const isSiteRoot = routePath === '/'
445
+ const frontmatterIsRoot = Boolean(metadata.frontmatter?.isRoot)
446
+ const hidden = isSpecialPage
447
+ ? true
448
+ : frontmatterHidden === false
449
+ ? false
450
+ : frontmatterHidden === true
451
+ ? true
452
+ : frontmatterIsRoot
444
453
  return {
445
454
  routePath,
446
455
  routeHref: withBase(routePath),
447
- filePath,
456
+ path,
448
457
  source,
449
458
  relativePath: relPath,
450
459
  name: baseName,
@@ -452,11 +461,10 @@ export const buildPageEntry = async ({ filePath, pagesDir, source }) => {
452
461
  segments,
453
462
  depth: segments.length,
454
463
  isIndex,
455
- isInternal: isInternalPage(baseName),
456
464
  title: metadata.title || derived?.title || (baseName === 'index' ? (dirName || 'Home') : baseName),
457
465
  weight: parseWeight(metadata.frontmatter?.weight),
458
466
  date: parseDate(metadata.frontmatter?.date) || parseDate(stats.mtime),
459
- isRoot: Boolean(metadata.frontmatter?.isRoot),
467
+ isRoot: isSiteRoot || frontmatterIsRoot,
460
468
  hidden,
461
469
  hiddenByFrontmatter,
462
470
  exclude,
@@ -468,9 +476,7 @@ export const buildPageEntry = async ({ filePath, pagesDir, source }) => {
468
476
  size: stats.size,
469
477
  createdAt: stats.birthtime?.toISOString?.() || null,
470
478
  updatedAt: stats.mtime?.toISOString?.() || null
471
- },
472
- createdAt: stats.birthtime?.toISOString?.() || null,
473
- updatedAt: stats.mtime?.toISOString?.() || null
479
+ }
474
480
  }
475
481
  }
476
482
 
@@ -481,7 +487,7 @@ const collectPagesFromDir = async (pagesDir, source) => {
481
487
  const pages = []
482
488
  for await (const page of walkPages(pagesDir)) {
483
489
  const entry = await buildPageEntry({
484
- filePath: page.filePath,
490
+ path: page.path,
485
491
  pagesDir,
486
492
  source
487
493
  })
@@ -523,7 +529,12 @@ const collectPages = async () => {
523
529
 
524
530
  const buildIndexFallback = (pages, siteName) => {
525
531
  const visiblePages = pages
526
- .filter((page) => !page.isInternal && page.routePath !== '/')
532
+ .filter(
533
+ (page) =>
534
+ page.routePath !== '/' &&
535
+ page.routePath !== '/404' &&
536
+ page.routePath !== '/offline'
537
+ )
527
538
  .sort((a, b) => a.routePath.localeCompare(b.routePath))
528
539
 
529
540
  const lines = [
@@ -574,7 +585,7 @@ const buildNavSequence = (nodes, pagesByRoute) => {
574
585
  const seen = new Set()
575
586
  const addEntry = (entry) => {
576
587
  if (!entry.routePath) return
577
- const key = entry.filePath || entry.routePath
588
+ const key = entry.path || entry.routePath
578
589
  if (seen.has(key)) return
579
590
  seen.add(key)
580
591
  result.push(entry)
@@ -616,14 +627,13 @@ export const buildPagesContext = async ({ compileAll = true } = {}) => {
616
627
  pages.unshift({
617
628
  routePath: '/',
618
629
  routeHref: withBase('/'),
619
- filePath: resolve(state.PAGES_DIR, 'index.md'),
630
+ path: resolve(state.PAGES_DIR, 'index.md'),
620
631
  relativePath: 'index.md',
621
632
  name: 'index',
622
633
  dir: '',
623
634
  segments: [],
624
635
  depth: 0,
625
636
  isIndex: true,
626
- isInternal: false,
627
637
  title: state.SITE_NAME || 'Methanol Site',
628
638
  weight: null,
629
639
  date: null,
@@ -648,10 +658,10 @@ export const buildPagesContext = async ({ compileAll = true } = {}) => {
648
658
  }
649
659
  }
650
660
  const getPageByRoute = (routePath, options = {}) => {
651
- const { filePath } = options || {}
652
- if (filePath) {
661
+ const { path } = options || {}
662
+ if (path) {
653
663
  for (const page of pages) {
654
- if (page.routePath === routePath && page.filePath === filePath) {
664
+ if (page.routePath === routePath && page.path === path) {
655
665
  return page
656
666
  }
657
667
  }
@@ -717,26 +727,26 @@ export const buildPagesContext = async ({ compileAll = true } = {}) => {
717
727
  pagesTree,
718
728
  getPagesTree,
719
729
  derivedTitleCache: pageDerivedCache,
720
- setDerivedTitle: (filePath, title, toc) => {
721
- if (!filePath) return
722
- pageDerivedCache.set(filePath, { title, toc })
730
+ setDerivedTitle: (path, title, toc) => {
731
+ if (!path) return
732
+ pageDerivedCache.set(path, { title, toc })
723
733
  },
724
- clearDerivedTitle: (filePath) => {
725
- if (!filePath) return
726
- pageDerivedCache.delete(filePath)
734
+ clearDerivedTitle: (path) => {
735
+ if (!path) return
736
+ pageDerivedCache.delete(path)
727
737
  },
728
738
  refreshPagesTree: () => {
729
739
  pagesTreeCache.clear()
730
740
  navSequenceCache.clear()
731
741
  pagesContext.pagesTree = getPagesTree('/')
732
742
  },
733
- getSiblings: (routePath, filePath = null) => {
743
+ getSiblings: (routePath, path = null) => {
734
744
  if (!routePath) return { prev: null, next: null }
735
745
  const sequence = getNavSequence(routePath)
736
746
  if (!sequence.length) return { prev: null, next: null }
737
747
  let index = -1
738
- if (filePath) {
739
- index = sequence.findIndex((entry) => entry.filePath === filePath)
748
+ if (path) {
749
+ index = sequence.findIndex((entry) => entry.path === path)
740
750
  }
741
751
  if (index < 0) {
742
752
  index = sequence.findIndex((entry) => entry.routePath === routePath)
@@ -748,7 +758,7 @@ export const buildPagesContext = async ({ compileAll = true } = {}) => {
748
758
  routePath: entry.routePath,
749
759
  routeHref: entry.routeHref,
750
760
  title: entry.title || entry.name || entry.routePath,
751
- filePath: entry.filePath || null
761
+ path: entry.path || null
752
762
  }
753
763
  }
754
764
  return {
@@ -775,7 +785,7 @@ export const buildPagesContext = async ({ compileAll = true } = {}) => {
775
785
  for (let i = 0; i < pages.length; i++) {
776
786
  const page = pages[i]
777
787
  if (logEnabled) {
778
- stageLogger.update(compileToken, `Compiling MDX [${i + 1}/${totalPages}] ${page.filePath}`)
788
+ stageLogger.update(compileToken, `Compiling MDX [${i + 1}/${totalPages}] ${page.path}`)
779
789
  }
780
790
  await compilePageMdx(page, pagesContext, {
781
791
  lazyPagesTree: true,
@@ -110,7 +110,7 @@ export const preparePublicAssets = async ({ themeDir, userDir, targetDir }) => {
110
110
  }
111
111
  }
112
112
 
113
- export const updateAsset = async ({ type, filePath, themeDir, userDir, targetDir, relPath }) => {
113
+ export const updateAsset = async ({ type, path, themeDir, userDir, targetDir, relPath }) => {
114
114
  const targetPath = resolve(targetDir, relPath)
115
115
 
116
116
  if (type === 'unlink') {
@@ -58,7 +58,7 @@ export function env(parentEnv) {
58
58
  const component = ({ children: childrenProp, ...props }, ...children) => {
59
59
  const id = renderCount++
60
60
  const idStr = id.toString(16)
61
- const script = `$$rwnd(${JSON.stringify(key)},${id},${Object.keys(props).length ? JSON5.stringify(props) : '{}'})`
61
+ const script = `$$rfrm(${JSON.stringify(key)},${id},${Object.keys(props).length ? JSON5.stringify(props) : '{}'})`
62
62
 
63
63
  return (R) => {
64
64
  return [
@@ -76,8 +76,8 @@ const resolvePagesRoot = (filePath) => {
76
76
 
77
77
  export const linkResolve = () => {
78
78
  return (tree, file) => {
79
- const baseDir = file?.path ? dirname(file.path) : file?.cwd || process.cwd()
80
- const pagesRoot = resolvePagesRoot(file?.path || null)
79
+ const baseDir = file.path ? dirname(file.path) : file.cwd || process.cwd()
80
+ const pagesRoot = resolvePagesRoot(file.path || null)
81
81
  visit(tree, (node) => {
82
82
  if (!isElement(node) || node.tagName !== 'a') {
83
83
  return
@@ -18,7 +18,10 @@
18
18
  * under the License.
19
19
  */
20
20
 
21
+ import { style } from './logger.js'
22
+
21
23
  const now = () => (typeof performance !== 'undefined' ? performance.now() : Date.now())
24
+ const log = console.log.bind(console)
22
25
 
23
26
  export const createStageLogger = (enabled) => {
24
27
  let lastLength = 0
@@ -26,13 +29,13 @@ export const createStageLogger = (enabled) => {
26
29
  const writeLine = (text, newline) => {
27
30
  if (!process.stdout || !process.stdout.write) {
28
31
  if (newline) {
29
- console.log(text)
32
+ log(text)
30
33
  }
31
34
  return
32
35
  }
33
36
  if (!isTty) {
34
37
  if (newline) {
35
- console.log(text)
38
+ log(text)
36
39
  }
37
40
  return
38
41
  }
@@ -43,17 +46,18 @@ export const createStageLogger = (enabled) => {
43
46
  }
44
47
  const start = (label) => {
45
48
  if (!enabled) return null
46
- writeLine(`${label}...`, false)
49
+ writeLine(`${style.cyan('◼')} ${label}...`, false)
47
50
  return { label, start: now() }
48
51
  }
49
52
  const update = (token, message) => {
50
53
  if (!enabled || !token || !message) return
51
- writeLine(message, false)
54
+ writeLine(`${style.cyan('◼')} ${message}`, false)
52
55
  }
53
56
  const end = (token) => {
54
57
  if (!enabled || !token) return
55
- const duration = Math.round(now() - token.start)
56
- writeLine(`${token.label}...\t${duration}ms`, true)
58
+ const duration = now() - token.start
59
+ const timeString = duration > 1000 ? `${(duration / 1000).toFixed(2)}s` : `${Math.round(duration)}ms`
60
+ writeLine(`${style.green('✔')} ${token.label}\t${style.dim(timeString)}`, true)
57
61
  }
58
62
  return { start, update, end }
59
63
  }