mirror of
https://github.com/quartz-community/utils.git
synced 2026-07-22 02:50:27 +00:00
feat: add getBasePath and resolveBasePath for subdirectory deployments
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.
This commit is contained in:
parent
81189f697c
commit
d7d93758b2
9 changed files with 78 additions and 6 deletions
2
dist/index.d.ts
vendored
2
dist/index.d.ts
vendored
|
|
@ -1,4 +1,4 @@
|
|||
export { RelativeURL, SimpleSlug, TransformOptions, endsWith, getAllSegmentPrefixes, getFileExtension, getFullSlug, getFullSlugFromUrl, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, pathToRoot, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix } from './path.js';
|
||||
export { RelativeURL, SimpleSlug, TransformOptions, endsWith, getAllSegmentPrefixes, getBasePath, getFileExtension, getFullSlug, getFullSlugFromUrl, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, pathToRoot, resolveBasePath, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix } from './path.js';
|
||||
export { normalizeRelativeURLs, registerEscapeHandler, removeAllChildren } from './dom.js';
|
||||
export { capitalize, classNames } from './lang.js';
|
||||
export { escapeHTML, unescapeHTML } from './escape.js';
|
||||
|
|
|
|||
11
dist/index.js
vendored
11
dist/index.js
vendored
|
|
@ -75,6 +75,15 @@ function resolvePath(to) {
|
|||
if (to.startsWith("/")) return to;
|
||||
return "/" + to;
|
||||
}
|
||||
function getBasePath() {
|
||||
if (typeof document === "undefined") return "";
|
||||
return document.body?.dataset?.basepath ?? "";
|
||||
}
|
||||
function resolveBasePath(to, basePath) {
|
||||
const base = basePath ?? getBasePath();
|
||||
const slug = to.startsWith("/") ? to : "/" + to;
|
||||
return base + slug;
|
||||
}
|
||||
function endsWith(s, suffix) {
|
||||
return s === suffix || s.endsWith("/" + suffix);
|
||||
}
|
||||
|
|
@ -275,6 +284,6 @@ function htmlToJsx(tree, components) {
|
|||
});
|
||||
}
|
||||
|
||||
export { capitalize, classNames, endsWith, escapeHTML, getAllSegmentPrefixes, getFileExtension, getFullSlug, getFullSlugFromUrl, htmlToJsx, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, normalizeRelativeURLs, pathToRoot, registerEscapeHandler, removeAllChildren, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix, unescapeHTML };
|
||||
export { capitalize, classNames, endsWith, escapeHTML, getAllSegmentPrefixes, getBasePath, getFileExtension, getFullSlug, getFullSlugFromUrl, htmlToJsx, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, normalizeRelativeURLs, pathToRoot, registerEscapeHandler, removeAllChildren, resolveBasePath, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix, unescapeHTML };
|
||||
//# sourceMappingURL=index.js.map
|
||||
//# sourceMappingURL=index.js.map
|
||||
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
8
dist/path.d.ts
vendored
8
dist/path.d.ts
vendored
|
|
@ -24,6 +24,12 @@ declare function getFullSlugFromUrl(): FullSlug;
|
|||
declare function slugifyFilePath(fp: FilePath, excludeExt?: boolean): FullSlug;
|
||||
declare function joinSegments(...args: string[]): string;
|
||||
declare function resolvePath(to: string): string;
|
||||
/** Read the base path injected at build time via `data-basepath` on `<body>`.
|
||||
* Returns `""` for root deployments, e.g. `"/repository"` for subdirectory. */
|
||||
declare function getBasePath(): string;
|
||||
/** Resolve a slug to an absolute URL path, prepending the site's base path.
|
||||
* e.g. `resolveBasePath("features/Callouts")` → `"/repository/features/Callouts"` */
|
||||
declare function resolveBasePath(to: string, basePath?: string): string;
|
||||
declare function endsWith(s: string, suffix: string): boolean;
|
||||
declare function trimSuffix(s: string, suffix: string): string;
|
||||
declare function stripSlashes(s: string, onlyStripPrefix?: boolean): string;
|
||||
|
|
@ -37,4 +43,4 @@ declare function slugTag(tag: string): string;
|
|||
declare function transformInternalLink(link: string): RelativeURL;
|
||||
declare function transformLink(src: FullSlug, target: string, opts: TransformOptions): RelativeURL;
|
||||
|
||||
export { type RelativeURL, type SimpleSlug, type TransformOptions, endsWith, getAllSegmentPrefixes, getFileExtension, getFullSlug, getFullSlugFromUrl, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, pathToRoot, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix };
|
||||
export { type RelativeURL, type SimpleSlug, type TransformOptions, endsWith, getAllSegmentPrefixes, getBasePath, getFileExtension, getFullSlug, getFullSlugFromUrl, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, pathToRoot, resolveBasePath, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix };
|
||||
|
|
|
|||
11
dist/path.js
vendored
11
dist/path.js
vendored
|
|
@ -72,6 +72,15 @@ function resolvePath(to) {
|
|||
if (to.startsWith("/")) return to;
|
||||
return "/" + to;
|
||||
}
|
||||
function getBasePath() {
|
||||
if (typeof document === "undefined") return "";
|
||||
return document.body?.dataset?.basepath ?? "";
|
||||
}
|
||||
function resolveBasePath(to, basePath) {
|
||||
const base = basePath ?? getBasePath();
|
||||
const slug = to.startsWith("/") ? to : "/" + to;
|
||||
return base + slug;
|
||||
}
|
||||
function endsWith(s, suffix) {
|
||||
return s === suffix || s.endsWith("/" + suffix);
|
||||
}
|
||||
|
|
@ -184,6 +193,6 @@ function _addRelativeToStart(s) {
|
|||
return s;
|
||||
}
|
||||
|
||||
export { endsWith, getAllSegmentPrefixes, getFileExtension, getFullSlug, getFullSlugFromUrl, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, pathToRoot, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix };
|
||||
export { endsWith, getAllSegmentPrefixes, getBasePath, getFileExtension, getFullSlug, getFullSlugFromUrl, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, pathToRoot, resolveBasePath, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix };
|
||||
//# sourceMappingURL=path.js.map
|
||||
//# sourceMappingURL=path.js.map
|
||||
2
dist/path.js.map
vendored
2
dist/path.js.map
vendored
File diff suppressed because one or more lines are too long
|
|
@ -4,6 +4,8 @@ export {
|
|||
getFullSlugFromUrl,
|
||||
joinSegments,
|
||||
resolvePath,
|
||||
getBasePath,
|
||||
resolveBasePath,
|
||||
endsWith,
|
||||
trimSuffix,
|
||||
stripSlashes,
|
||||
|
|
|
|||
15
src/path.ts
15
src/path.ts
|
|
@ -107,6 +107,21 @@ export function resolvePath(to: string): string {
|
|||
return "/" + to;
|
||||
}
|
||||
|
||||
/** Read the base path injected at build time via `data-basepath` on `<body>`.
|
||||
* Returns `""` for root deployments, e.g. `"/repository"` for subdirectory. */
|
||||
export function getBasePath(): string {
|
||||
if (typeof document === "undefined") return "";
|
||||
return document.body?.dataset?.basepath ?? "";
|
||||
}
|
||||
|
||||
/** Resolve a slug to an absolute URL path, prepending the site's base path.
|
||||
* e.g. `resolveBasePath("features/Callouts")` → `"/repository/features/Callouts"` */
|
||||
export function resolveBasePath(to: string, basePath?: string): string {
|
||||
const base = basePath ?? getBasePath();
|
||||
const slug = to.startsWith("/") ? to : "/" + to;
|
||||
return base + slug;
|
||||
}
|
||||
|
||||
export function endsWith(s: string, suffix: string): boolean {
|
||||
return s === suffix || s.endsWith("/" + suffix);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import {
|
|||
simplifySlug,
|
||||
joinSegments,
|
||||
resolvePath,
|
||||
resolveBasePath,
|
||||
endsWith,
|
||||
trimSuffix,
|
||||
stripSlashes,
|
||||
|
|
@ -105,3 +106,33 @@ describe("getAllSegmentPrefixes", () => {
|
|||
expect(getAllSegmentPrefixes("a/b/c")).toEqual(["a", "a/b", "a/b/c"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveBasePath", () => {
|
||||
it("prepends explicit basePath to slug", () => {
|
||||
expect(resolveBasePath("features/Callouts", "/repository")).toBe(
|
||||
"/repository/features/Callouts",
|
||||
);
|
||||
});
|
||||
|
||||
it("prepends explicit basePath to slug with leading slash", () => {
|
||||
expect(resolveBasePath("/features/Callouts", "/repository")).toBe(
|
||||
"/repository/features/Callouts",
|
||||
);
|
||||
});
|
||||
|
||||
it("returns just /slug when basePath is empty (root deployment)", () => {
|
||||
expect(resolveBasePath("features/Callouts", "")).toBe("/features/Callouts");
|
||||
});
|
||||
|
||||
it("handles empty slug with basePath", () => {
|
||||
expect(resolveBasePath("", "/repository")).toBe("/repository/");
|
||||
});
|
||||
|
||||
it("handles empty slug with empty basePath", () => {
|
||||
expect(resolveBasePath("", "")).toBe("/");
|
||||
});
|
||||
|
||||
it("falls back to getBasePath() when no basePath argument (server-side returns empty)", () => {
|
||||
expect(resolveBasePath("page")).toBe("/page");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue