Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/components/scripts/currentSlug.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { getBasePath, getFullSlugFromUrl, simplifySlug } from "@quartz-community/utils";

export interface GraphSlugInput {
canonicalSlug?: string;
urlSlug: string;
basePath: string;
}

export function getCurrentGraphSlug(): string {
const canonicalSlug = document.body?.dataset?.slug;
return resolveGraphSlug({
canonicalSlug,
urlSlug: canonicalSlug ? "" : getFullSlugFromUrl(),
basePath: canonicalSlug ? "" : getBasePath(),
});
}

export function resolveGraphSlug({ canonicalSlug, urlSlug, basePath }: GraphSlugInput): string {
let slug = canonicalSlug || urlSlug;

if (!canonicalSlug) {
const base = basePath.replace(/^\//, "").replace(/\/$/, "");
if (base && (slug === base || slug.startsWith(`${base}/`))) {
slug = slug.slice(base.length);
if (slug.startsWith("/")) slug = slug.slice(1);
}
}

const simplified = simplifySlug(slug);
return simplified === "" ? "index" : simplified;
}
17 changes: 3 additions & 14 deletions src/components/scripts/graph.inline.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
// @ts-nocheck
import {
removeAllChildren,
getBasePath,
getFullSlugFromUrl,
simplifySlug,
resolveBasePath,
} from "@quartz-community/utils";
import { removeAllChildren, simplifySlug, resolveBasePath } from "@quartz-community/utils";
import { getCurrentGraphSlug } from "./currentSlug";

(function () {
function getSlugFromUrl() {
var slug = getFullSlugFromUrl();
var base = getBasePath();
if (base && slug.startsWith(base.replace(/^\//, ""))) {
slug = slug.slice(base.replace(/^\//, "").length);
if (slug.startsWith("/")) slug = slug.slice(1);
}
return slug;
return getCurrentGraphSlug();
}

function loadScript(src) {
Expand Down
87 changes: 87 additions & 0 deletions test/currentSlug.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { describe, expect, it } from "vitest";
import { getCurrentGraphSlug, resolveGraphSlug } from "../src/components/scripts/currentSlug";

describe("resolveGraphSlug", () => {
it("canonicalizes a Quartz folder-page body slug to the graph index key", () => {
expect(
resolveGraphSlug({
canonicalSlug: "projects/example/index",
urlSlug: "projects/example",
basePath: "",
}),
).toBe("projects/example/");
});

it("preserves a trailing-slash folder URL when body metadata is unavailable", () => {
expect(
resolveGraphSlug({
canonicalSlug: undefined,
urlSlug: "projects/example/",
basePath: "",
}),
).toBe("projects/example/");
});

it("preserves an ordinary page slug from body metadata", () => {
expect(
resolveGraphSlug({
canonicalSlug: "hermes/overview",
urlSlug: "hermes/overview",
basePath: "",
}),
).toBe("hermes/overview");
});

it("preserves an ordinary page slug through the URL fallback", () => {
expect(
resolveGraphSlug({
canonicalSlug: undefined,
urlSlug: "hermes/overview",
basePath: "",
}),
).toBe("hermes/overview");
});

it("strips the configured base path from the URL fallback", () => {
expect(
resolveGraphSlug({
canonicalSlug: undefined,
urlSlug: "archive/projects/example/",
basePath: "/archive",
}),
).toBe("projects/example/");
});

it("does not strip a similar URL path segment", () => {
expect(
resolveGraphSlug({
canonicalSlug: undefined,
urlSlug: "archives/projects/example/",
basePath: "/archive",
}),
).toBe("archives/projects/example/");
});

it("uses Quartz's browser URL and base-path utilities for the fallback", () => {
const previousWindow = Object.getOwnPropertyDescriptor(globalThis, "window");
const previousDocument = Object.getOwnPropertyDescriptor(globalThis, "document");

Object.defineProperty(globalThis, "window", {
configurable: true,
value: { location: { pathname: "/archive/hermes/overview/" } },
});
Object.defineProperty(globalThis, "document", {
configurable: true,
value: { body: { dataset: { basepath: "/archive" } } },
});

try {
expect(getCurrentGraphSlug()).toBe("hermes/overview");
} finally {
if (previousWindow) Object.defineProperty(globalThis, "window", previousWindow);
else Reflect.deleteProperty(globalThis, "window");
if (previousDocument) Object.defineProperty(globalThis, "document", previousDocument);
else Reflect.deleteProperty(globalThis, "document");
}
});
});