Commit Graph

945 Commits

Author SHA1 Message Date
saberzero1 7076a897e1 chore: formatting 2026-07-30 15:43:15 +02:00
saberzero1 41864a0eba refactor: replace createRequire with import.meta.resolve in config-loader and gitLoader 2026-07-27 20:47:51 +02:00
saberzero1 508f73a33f feat: replace CJS require with static imports, add comprehensive layout system tests 2026-07-27 20:23:31 +02:00
saberzero1 a121fd2e96 feat: unify layout slot architecture - make header/footer configurable positions, footer as array, add defaultPosition fallback, add tests, update docs 2026-07-27 17:32:40 +02:00
saberzero1 94fcabb0b4 feat: add @quartz-themes/core to config and templates
Add disabled theme entry to default config and default/blog templates.
Migrate obsidian and ttrpg templates from git-based quartz-themes source
to npm @quartz-themes/core package.
2026-07-24 20:33:05 +02:00
saberzero1 26a5a86d77 feat: add @quartz-themes/core as a dependency
Add @quartz-themes/core to dependencies and @quartz-themes/ to shared
scopes so theme packages are treated as externals by the plugin bundler.
2026-07-24 20:32:52 +02:00
saberzero1 a791a4f12d fix: disable font ligatures on code blocks (#2428) 2026-07-24 00:43:31 +02:00
Emile Bangma 581f6707da fix: decouple Head.tsx from og-image plugin import (#2495)
Remove unconditional import of CustomOgImagesEmitterName from
.quartz/plugins in Head.tsx. This caused builds to fail when the
og-image plugin was not listed in quartz.config.yaml, violating the
plugin system's opt-in contract.

The fix inlines the emitter name string constant at the usage site.

Also convert the ContentDetails import in fileTrie.ts to
`import type` since it is only used in a type position.
2026-07-23 15:30:37 +02:00
saberzero1 966307e0d0 style: format docs/hosting.md and loader/index.ts 2026-07-23 09:26:51 +02:00
saberzero1 11b9960663 feat: migrate to npm specifiers with type-safe plugin index
- Default config and all 4 templates use @quartz-community/* npm specifiers
- config-loader: npm packages imported directly (not via .quartz/plugins/ paths)
- gitLoader: regeneratePluginIndex cross-references .d.ts with .js to correctly
  classify type-only exports, preventing runtime 'does not provide export' errors
- All 44 default plugins added as dependencies
- Locally tested: 111 docs files → 374 output files, zero errors
2026-07-23 02:19:17 +02:00
saberzero1 4b7ecb96f0 revert: restore github: specifiers in default config and templates
The npm specifier path requires additional work in the esbuild
transpilation pipeline to mark npm imports as external. Reverting
to github: specifiers to restore the docs site immediately.

The npm loader code (parsePluginSource, config-loader, CLI) remains
in place for future use. Only the default config/templates are reverted.
2026-07-23 02:06:45 +02:00
saberzero1 fe1f1d30aa fix: add npm plugin dependencies and fix fonts package name
- Added all 44 default plugins as dependencies so npm ci installs them
- Fixed @quartz-community/fonts → @quartz-community/quartz-fonts (actual npm name)
- Regenerated package-lock.json with plugin dependencies
2026-07-23 01:46:28 +02:00
saberzero1 97eea3ee34 feat: migrate default config and templates to npm specifiers
- quartz.config.default.yaml: all 44 plugins use @quartz-community/* npm specifiers
- cli/templates/*.yaml: all 4 templates updated (default, blog, obsidian, ttrpg)
- bootstrap-cli.mjs: updated help text
- package.json: devDeps use npm semver ranges instead of github: specifiers
- gitLoader.ts: regeneratePluginIndex scans npm packages from node_modules
- install-plugins.ts: generates plugin index for npm packages
- Removed quartz.lock.json (only relevant for git-installed plugins)
2026-07-23 01:29:25 +02:00
saberzero1 de21613607 style: format loader files 2026-07-23 01:19:21 +02:00
saberzero1 5b34917e98 feat: support npm scoped package specifiers for plugins
Plugins can now be referenced as "@quartz-community/<name>" in
quartz.config.yaml and via 'quartz plugin add'. The npm path skips
git installation and resolves from node_modules.

Changes:
- gitLoader.ts: detect @scope/name as npm package in parsePluginSource()
- config-loader.ts: skip git install for npm packages, read manifests
  from node_modules via createRequire
- install-plugins.ts: filter npm packages from prebuild, fallback to
  YAML config parsing to avoid loading full quartz.ts
- plugin-data.js: npm detection in CLI parseGitSource()
- plugin-git-handlers.js: npm install path in handlePluginAdd()
- package.json: add missing hast-util-from-html dependency
2026-07-23 01:17:53 +02:00
Narath Carlile e12ca11100 fix: watch quartz.config.yaml during serve (#2448)
The serve-mode watcher globs never matched quartz.config.yaml or
quartz.config.default.yaml, so config edits (theme colors, plugin
flags, footer links) silently required a server restart. This was a
regression from v4, where quartz.config.ts matched the **/*.ts glob.
2026-06-15 20:19:27 -04:00
saberzero1 8a79f59abb chore: configure fonts plugin in templates 2026-06-10 23:17:19 +02:00
saberzero1 f15aa0032a fix: allow updating when repository is generated from template 2026-05-27 20:43:56 +02:00
saberzero1 3138a88bb1 chore: updated layouts to include table of contents 2026-05-27 00:18:06 +02:00
saberzero1 db5aca2b8d fix: apply default position when installing plugins 2026-05-27 00:17:45 +02:00
saberzero1 4579e49465 test: regression tests for junctions 2026-05-26 21:15:36 +02:00
saberzero1 882d3b3f50 fix: fall back to junctions on windows 2026-05-26 21:15:20 +02:00
saberzero1 b24f2a5e7b test: add regression tests for baseurl in serve mode 2026-05-26 12:56:32 +02:00
saberzero1 ad685b8d4e fix: use correct baseurl in serve mode 2026-05-26 12:56:18 +02:00
saberzero1 cbe101dc12 chore: updated configuration templates 2026-05-25 03:15:41 +02:00
saberzero1 9f7caa96f4 chore: updated og-image 2026-05-24 18:50:02 +02:00
Michael Cordell d45b7a7bf6 fix(dispatcher): skip undefined components in collectComponents (#2404)
layout.footer (and other optional layout slots) can be undefined
when disabled. Adding undefined to the seen Set caused a crash in
componentResources.ts when destructuring component properties.
2026-05-24 17:51:42 +02:00
saberzero1 2455c87167 fix: show help on invalid CLI commands and debounce watch rebuilds
- Change .showHelpOnFail(false) to true for better new-user UX
- Add 100ms debounce to watch mode rebuilds to batch rapid file changes
2026-05-24 17:23:11 +02:00
saberzero1 0d9b356046 fix: resolve client-side navigation and popover issues
- Fix popover crash on missing Content-Type header (null check)
- Fix SPA loading bar corrupting page via micromorph interference
  (remove bar before morph, use ephemeral DOM elements instead of
  persistent reference)
- Add stopLoading() cleanup in navigation finally block
2026-05-24 17:10:03 +02:00
saberzero1 7f00400ad2 fix: improve CLI error handling and user guidance
- Add Node.js >= 22 runtime version check before any imports
- Add EADDRINUSE error handlers for HTTP and WebSocket servers
- Fix misleading 'Couldn't parse Quartz configuration' error message
- Add actionable guidance to sync/upgrade/push failure messages
- Add --concurrency validation (must be >= 1)
2026-05-24 17:09:56 +02:00
saberzero1 caa55037f7 fix: harden core build system against silent failures
- Wrap rebuild() in try/finally to guarantee mutex release (prevents deadlock)
- Surface rebuild errors via .catch() instead of discarding with void
- Add null checks for vfile.data.relativePath (prevents crash on virtual files)
- Add try-finally for worker pool cleanup in parse.ts (prevents thread leaks)
- Remove process.exit(1) from parse error handler (let errors propagate)
- Add per-emitter error handling in emit phase with degraded-build warning
- Replace unsafe Map.get()! assertions with null-checked access in config-loader
2026-05-24 17:09:46 +02:00
saberzero1 dfde22acfd feat: emit plugin scripts individually instead of bundling into postscript 2026-05-23 19:51:55 +02:00
saberzero1 b1e5d3a7cc test: add regression tests for transclusion changes 2026-05-23 01:29:24 +02:00
saberzero1 4d715774e1 fix: properly handle multiple transclusions 2026-05-23 01:29:10 +02:00
saberzero1 0593c8cd6a fix: allow arbitrary transclusion 2026-05-23 01:18:30 +02:00
saberzero1 2a02240802 feat: preload static resources 2026-05-22 23:12:37 +02:00
saberzero1 cfcd9c18ac feat: split and hash inlined assets 2026-05-22 23:03:39 +02:00
saberzero1 cfba672f51 feat: split and hash static css 2026-05-22 22:42:06 +02:00
saberzero1 7fd0590a46 fix: improved plugin type resolution 2026-05-21 17:59:26 +02:00
saberzero1 21ea5895cb fix: improved plugin validation on install 2026-05-20 23:23:39 +02:00
saberzero1 c8f6e6dc14 feat(css): make styles layered by default 2026-04-28 17:25:37 +02:00
saberzero1 9fcc3f260c fix: handle EEXIST race in peer dependency symlink creation 2026-04-27 22:34:31 +02:00
saberzero1 efd9e8e095 feat(loader): prefer pre-built plugins 2026-04-27 22:03:23 +02:00
saberzero1 a85c3bd814 refactor(theme): use Obsidian CSS custom property names 2026-04-25 23:13:50 +02:00
saberzero1 710db1f161 fix(components): deduplicate plugin handler registration 2026-04-24 23:56:53 +02:00
saberzero1 b3082c32dc fix(path): improper redirects in subpath domain sites 2026-04-22 18:25:05 +02:00
saberzero1 dc88017b37 feat(404): try redirect to lowercase URL 2026-04-19 21:44:23 +02:00
saberzero1 f370898c56 fix(config): properly pass ts-based options to plugins 2026-04-17 22:14:36 +02:00
saberzero1 c32d11cb8b fix(build): remove extension-stripped slug aliases that pollute allSlugs
addVirtualPageSlugAliases injected extension-stripped aliases for
every PageType-registered extension into ctx.allSlugs (e.g. for
`Canvas.canvas` it added an alias `canvas`). Intended to help
`![[file.canvas]]` transclusions resolve to virtual pages, but:

1. CrawlLinks' shortest strategy treats allSlugs entries as real
   files. When an author writes `[[Canvas]]` in a note, shortest
   lookup matches BOTH the alias `canvas` and real basenames
   like `features/canvas`. With matchingFileNames.length === 2,
   the uniqueness check fails and transformLink falls back to
   absolute resolution, producing a dead href `./canvas` that
   points to no emitted file.

2. The aliases were never actually needed for transclusion.
   renderPage.tsx already has its own extension-stripping
   fallback (lines 107-119) that consults allFiles directly.
   Virtual pages (canvas-page, bases-page) emit at slugs that
   KEEP their extension (e.g. `canvas.canvas`), so
   `![[Canvas.canvas]]` resolves naturally without any alias.

3. The aliases mispresent Obsidian semantics. In Obsidian,
   `[[Canvas]]` resolves to `Canvas.md`; non-md files require
   the explicit extension (`[[Canvas.canvas]]`). Injecting
   extension-stripped aliases into allSlugs made Quartz claim
   bare names can refer to non-md virtual pages, which is
   wrong.

Reproduction: docs/features/index.md contains `[[Canvas]]` which
should resolve to docs/features/Canvas.md (slug features/canvas).
Under the old behavior it produced href="../canvas" with
data-slug="canvas" pointing nowhere. After this fix it produces
href="../features/canvas" with data-slug="features/canvas"
correctly.

Verified with fresh `npx quartz build -d docs`:
- [[Canvas]] → ./features/canvas ✓
- ![[Canvas.canvas]] transclusion still works ✓
- ![[Base.base]] virtual page still emits ✓
- 0 internal broken links across all output ✓
- all 91 existing tests pass
2026-04-17 03:05:36 +02:00
saberzero1 17d5ae76bf refactor(util/path): re-export normalizeHastElement from @quartz-community/utils
The normalizeHastElement helper and its internal _rebaseHastElement
have been promoted to @quartz-community/utils so that plugins can
consume the same cross-slug HAST rebasing logic Quartz core uses
for transclude expansion. Previously they lived only in Quartz's
internal util/path module, which out-of-tree plugins (e.g.
canvas-page, whose buildEmbeddedContent embeds vfile.data.htmlAst
from arbitrary pages) could not import from.

normalizeRelativeURLs and its DOM-element sibling _rebaseHtmlElement
stay local - those operate on DOM Elements at runtime, not HAST AST
nodes, and belong with Quartz's DOM-specific code.
2026-04-17 02:27:48 +02:00