bundle() and generateSitemap() are plain workers now; build() wraps
them in tasks alongside render. Keeps the MPA asset copies and the
MPA client build under the bundles spinner instead of running after
it resolves, and skips the sitemap spinner when sitemap generation
is off.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Expose the any-typed highlight escape hatch on the exported
MarkdownRenderer type and accept it in the preConfig/config hooks,
instead of special-casing only the internal singleton.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Default codepoint sort matches the pages sort below and is not
locale/ICU dependent; route order is only consumed by exact-match
lookups, so ordering stays unobservable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Move the rendering pages body into a standalone render() invoked
via bind, taking the bundle output whole. The SSR entry import now
fails under the rendering spinner, and the hashmap.json write runs
inside the task alongside the other rendering outputs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hoist the groups[].name body out of resolveViteConfig into a
module-level function partially applied with themeEntryRE via bind,
instead of re-creating a closure over bundle() locals per config.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the remaining sync writes and the tempDir removal in
build()/generateMetadataScript() with fs/promises, and switch
linkVue to the async packageDirectory lookup with an async unlink.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Lets bundle() receive the build outputs from the spinner-wrapped
callback directly instead of smuggling them through outer let
bindings with a definite-assignment assertion.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Store the promise of the extracted loadData() directly in the
per-id map rather than resolving a hand-made pending promise at the
end of the load hook. This also propagates loader errors to the
other build's pending consumer, which previously awaited forever.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collapse the duplicated listen branches and await the listening
event; serve() now also rejects on listen errors like EADDRINUSE
instead of crashing in the callback.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Iterate the log parser with for-await instead of data/end/error
callbacks (spawn errors are forwarded by destroying the stream), and
await the single-file lookup with events.once, which rejects on
child error by itself.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pipeline() replaces the manual finish/error promise and also
surfaces SitemapStream errors, which pipe() never forwarded to the
write stream.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
once() also rejects if the child emits error first, so the manual
promise wiring is unnecessary.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Content, include, route-template and search reads now run
concurrently, so large sites can hit EMFILE/ENFILE. Route all async
reads through a shared readFile util that retries with backoff.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Expanding an include that is its own ancestor recursed forever.
Track the ancestor chain and leave such includes unexpanded; the
same file can still be included repeatedly as a sibling.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolve includes through replaceAsync and fs/promises so include
files are read without blocking the event loop while pages render
concurrently.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the existsSync pre-check in favor of catching ENOENT from the
read itself, and skip indexing when a page renders to nothing (file
gone or excluded via search: false) instead of feeding empty html to
the section splitter.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Split the block parser and fence renderer into factories, extract
region extraction, and type the snippet token instead of ts-ignoring
its src field.
Reading the file now handles ENOENT/EISDIR explicitly: a missing
snippet previously threw from statSync before the 'path not found'
message could render, so that branch was unreachable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
It is internal and its only caller passes every argument; apply the
fallbacks at the call site instead of hiding them in the signature
after the required siteConfig parameter.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Read the 404 page with fs/promises, replace the trimChar helper with
a regex, and flatten the if/else around listen.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Swap the remaining sync fs calls in renderPage for fs/promises,
switch head-script minification to the async minify API, and make
resolvePageImports async for the realpath call. Pages render under
buildConcurrency, so blocking calls here stall the whole batch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
createContentLoader already maps files with bounded concurrency, but
the sync stat/read calls serialized the actual I/O.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A fixed ui-custom name still gives adblock filter lists a stable
string to match on. Emit the Carbon/BuySellAds chunks with just the
content hash instead. Changes the emitted filenames for those chunks
and, transitively, the hashes of chunks that import them.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Now that dev updates actually reach the index, any changed markdown
file was being ingested — including srcExclude'd include partials and
dynamic route templates, which are not pages and produced dead search
results. Mirror the initial scan and only index files present in
siteConfig.pages.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
createContentLoader called md.renderAsync without a MarkdownEnv, so
the internal link plugin fell back to defaults and always emitted
.html links in rendered content and excerpts even with cleanUrls
enabled, and plugins reading env.path/relativePath broke. Build the
same env as a normal page render and forward it to both calls.
fixes#4331closes#5299
Co-authored-by: TowyTowy <towy@airreps.link>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Re-indexing only invalidated the bare @localSearchIndex module; the
per-locale modules that carry the data were still served from the
transform cache, and the browser module cache pinned them too. Version
the locale import in dev so every index update loads fresh data.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rewrites were computed from the locally globbed pages only, so pages
injected via the config were present in siteConfig.pages but never
entered the rewrites map.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
importerMap values were srcDir-relative paths computed with
path.posix.relative, which garbles on Windows drive-letter case
mismatches, and the delete cleanup used a relative key against the
absolute-keyed map so it never removed anything. Store module ids
instead, derive the cache key with a win32-aware relative, and prune
both the include entry and page references after invalidating.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The dead link check compares resolved links against source-space page
paths, so a link to the original location of a rewritten page passed
the check but 404s in the built site.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Discovered config files are keyed by their source directory, but the
lookup walked the rewrite-applied relativePath, so directories covered
by rewrites silently lost their additional config. Resolve against
pageData.filePath on both server and client, which also makes dynamic
route pages inherit configs from their route template's directory.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
URLs were derived from the source path only, so loader-generated links
pointed at the pre-rewrite location and 404ed for rewritten pages.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
indexFile expects a srcDir-relative page and joins it with srcDir, but
hotUpdate passed the absolute path, producing a doubled path that
failed the existence check — so edits never updated the local search
index. Regression from #3374.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The markdownToVue compile cache is keyed by the rewrite-applied
relativePath, but include-triggered invalidation passed the source
path, so pages with rewrites served stale content in dev when an
included file changed.
closes#5035
Co-authored-by: yyznm <yyz_nm@163.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A markdown or Vue file whose path contains the word "docsearch" was
intercepted by the @docsearch/css transform and never compiled,
failing the build. Check page extensions first.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Equivalent to re-applying the rewrite map manually, but hardened
against drive-letter case mismatches on Windows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Previously generateSitemap re-read and re-parsed every source file to
compute lastmod, reconstructing source paths from URLs. The transform
hook now records the already-computed pageData.lastUpdated per page,
keyed by its rewrite-applied relativePath. Dynamic route pages now get
a lastmod too (from their route template), which the old file lookup
could not resolve.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Standardizes the tone across the file and documents all previously
undocumented types and members.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>