The initial commit added normalizeHastElement to src/path.ts but
forgot to include it in src/index.ts's top-level re-export list,
so importers doing `import { normalizeHastElement } from '@quartz-community/utils'`
would see 'has no exported member'. Imports via the /path subpath
worked, but the top-level entrypoint is the conventional import
surface for most consumers.
Moved from Quartz core (quartz/util/path.ts) into the shared utils
package so that plugins performing cross-slug HAST embedding can
re-use the same rebase helper as Quartz's internal transclude
expansion, rather than reimplementing or skipping the rebase.
The primary consumer outside of Quartz core is canvas-page, whose
buildEmbeddedContent() pulls vfile.data.htmlAst from arbitrary target
pages and serializes it verbatim into canvas pages - producing broken
relative hrefs that survive accidentally on root deployments but fail
under non-trivial basePath configurations. Exposing the helper here
lets canvas-page (and any future embedding plugin) rebase correctly
without duplicating the logic.
Implementation details:
- Deep-clones the input via structuredClone (Node >=22 builtin) so
callers don't need to bring their own clone function
- Absolute URLs (http://, https://, /root-relative) pass through
untouched; only relative URLs are rebased
- Recurses into children so nested anchors inside a rebased subtree
are also normalized
Backed by 10 new tests covering same-slug, cross-slug (both directions),
nested depth, anchor preservation, absolute URL passthrough, root-relative
passthrough, src-attribute rebasing, elements without href/src, nested
children recursion, and input-immutability.
slugifyPath now lowercases its output, which cascades through
slugifyFilePath, slugTag, and transformInternalLink (all of which
funnel through _sluggify).
This matches Obsidian's case-insensitive link and tag matching:
[[MyNote]], [[mynote]], and [[MYNOTE]] all resolve to the slug
'my-note', and the tags #MyTag, #mytag, and #MYTAG collapse into a
single tag page.
BREAKING CHANGE: all generated URLs are now lowercase. Users
upgrading with mixed-case source filenames will see their URLs
change (e.g. /MyNote -> /my-note). Also eliminates silent data
loss on case-insensitive filesystems (macOS APFS, Windows NTFS)
where Apple.md and apple.md previously produced conflicting HTML
outputs that overwrote each other without warning.
When src is a folder page (e.g. 'Compendium/Spells' backed by index.md),
pathToRoot miscalculated the depth because the browser serves folder pages
at '/Compendium/Spells/' (trailing slash). Now detects folder pages via
allSlugs and uses the index slug for correct relative URL generation.
Add utility functions to resolve links correctly when Quartz is deployed
to a subdirectory (e.g., user.github.io/repository). getBasePath() reads
the base path from a data attribute on <body>, and resolveBasePath()
prepends it to slugs for client-side navigation.
With build tools (tsup, typescript) moved to devDependencies, the prepare
script can no longer build when npm fetches this package from GitHub (npm
does not install devDependencies for git dependencies). Commit the pre-built
dist/ output so GitHub-based installs work without a build step.