diff --git a/docs/plugins/AliasRedirects.md b/docs/plugins/AliasRedirects.md index 8c0365377..94ba43bcf 100644 --- a/docs/plugins/AliasRedirects.md +++ b/docs/plugins/AliasRedirects.md @@ -6,19 +6,39 @@ tags: This plugin emits HTML redirect pages for aliases and permalinks defined in the frontmatter of content files. -For example, A `foo.md` has the following frontmatter +## Aliases + +Aliases create redirects from alternative names to the actual page URL. + +For example, a `foo.md` has the following frontmatter: ```md title="foo.md" --- title: "Foo" alias: - "bar" + - "old-name" --- ``` -The target `host.me/bar` will be redirected to `host.me/foo` +The URLs `host.me/bar` and `host.me/old-name` will be redirected to `host.me/foo` -Note that these are permanent redirect. +## Permalinks + +Permalinks set the actual URL where the page will be accessed. When you set a permalink, the page is rendered at that URL instead of the default file path. + +For example, a `my-note.md` has the following frontmatter: + +```md title="my-note.md" +--- +title: "My Note" +permalink: "/custom-path" +--- +``` + +The page will be accessible at `host.me/custom-path` (not at `host.me/my-note`). A redirect will automatically be created from the original file path (`host.me/my-note`) to the permalink (`host.me/custom-path`). + +Note that these are permanent redirects. The emitter supports the following aliases: diff --git a/quartz/build.ts b/quartz/build.ts index f3adfe250..81abdf24f 100644 --- a/quartz/build.ts +++ b/quartz/build.ts @@ -49,6 +49,7 @@ async function buildQuartz(argv: Argv, mut: Mutex, clientRefresh: () => void) { cfg, allSlugs: [], allFiles: [], + slugToPermalink: {}, incremental: false, } @@ -84,6 +85,13 @@ async function buildQuartz(argv: Argv, mut: Mutex, clientRefresh: () => void) { const parsedFiles = await parseMarkdown(ctx, filePaths) const filteredContent = filterContent(ctx, parsedFiles) + // Build slugToPermalink map after parsing + for (const [_tree, file] of filteredContent) { + if (file.data.permalinkSlug && file.data.slug) { + ctx.slugToPermalink[file.data.slug] = file.data.permalinkSlug + } + } + await emitContent(ctx, filteredContent) console.log( styleText("green", `Done processing ${markdownPaths.length} files in ${perf.timeSince()}`), @@ -261,6 +269,14 @@ async function rebuild(changes: ChangeEvent[], clientRefresh: () => void, buildD .map((file) => file.content), ) + // Rebuild slugToPermalink map + ctx.slugToPermalink = {} + for (const [_tree, file] of processedFiles) { + if (file.data.permalinkSlug && file.data.slug) { + ctx.slugToPermalink[file.data.slug] = file.data.permalinkSlug + } + } + let emittedFiles = 0 for (const emitter of cfg.plugins.emitters) { // Try to use partialEmit if available, otherwise assume the output is static diff --git a/quartz/components/Backlinks.tsx b/quartz/components/Backlinks.tsx index 0d34457f3..0d783310a 100644 --- a/quartz/components/Backlinks.tsx +++ b/quartz/components/Backlinks.tsx @@ -1,6 +1,6 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" import style from "./styles/backlinks.scss" -import { resolveRelative, simplifySlug } from "../util/path" +import { resolveRelative, simplifySlug, getDisplaySlug } from "../util/path" import { i18n } from "../i18n" import { classNames } from "../util/lang" import OverflowListFactory from "./OverflowList" @@ -35,7 +35,10 @@ export default ((opts?: Partial) => { {backlinkFiles.length > 0 ? ( backlinkFiles.map((f) => (
  • - + {f.frontmatter?.title}
  • diff --git a/quartz/components/Breadcrumbs.tsx b/quartz/components/Breadcrumbs.tsx index 5144a314d..43690589f 100644 --- a/quartz/components/Breadcrumbs.tsx +++ b/quartz/components/Breadcrumbs.tsx @@ -1,6 +1,6 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" import breadcrumbsStyle from "./styles/breadcrumbs.scss" -import { FullSlug, SimpleSlug, resolveRelative, simplifySlug } from "../util/path" +import { FullSlug, SimpleSlug, resolveRelative, simplifySlug, getDisplaySlug } from "../util/path" import { classNames } from "../util/lang" import { trieFromAllFiles } from "../util/ctx" @@ -59,7 +59,7 @@ export default ((opts?: Partial) => { } const crumbs: CrumbData[] = pathNodes.map((node, idx) => { - const crumb = formatCrumb(node.displayName, fileData.slug!, simplifySlug(node.slug)) + const crumb = formatCrumb(node.displayName, getDisplaySlug(fileData), simplifySlug(node.slug)) if (idx === 0) { crumb.displayName = options.rootName } diff --git a/quartz/components/PageList.tsx b/quartz/components/PageList.tsx index 7bf23829c..e58a8fda4 100644 --- a/quartz/components/PageList.tsx +++ b/quartz/components/PageList.tsx @@ -1,4 +1,4 @@ -import { FullSlug, isFolderPath, resolveRelative } from "../util/path" +import { FullSlug, isFolderPath, resolveRelative, getDisplaySlug } from "../util/path" import { QuartzPluginData } from "../plugins/vfile" import { Date, getDate } from "./Date" import { QuartzComponent, QuartzComponentProps } from "./types" @@ -78,7 +78,10 @@ export const PageList: QuartzComponent = ({ cfg, fileData, allFiles, limit, sort

    - + {title}

    @@ -88,7 +91,7 @@ export const PageList: QuartzComponent = ({ cfg, fileData, allFiles, limit, sort
  • {tag} diff --git a/quartz/components/RecentNotes.tsx b/quartz/components/RecentNotes.tsx index 2c32feadf..06b2448ad 100644 --- a/quartz/components/RecentNotes.tsx +++ b/quartz/components/RecentNotes.tsx @@ -1,5 +1,5 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" -import { FullSlug, SimpleSlug, resolveRelative } from "../util/path" +import { FullSlug, SimpleSlug, resolveRelative, getDisplaySlug } from "../util/path" import { QuartzPluginData } from "../plugins/vfile" import { byDateAndAlphabetical } from "./PageList" import style from "./styles/recentNotes.scss" @@ -48,7 +48,10 @@ export default ((userOpts?: Partial) => {

    - + {title}

    @@ -64,7 +67,10 @@ export default ((userOpts?: Partial) => {
  • {tag} @@ -79,7 +85,7 @@ export default ((userOpts?: Partial) => { {opts.linkToMore && remaining > 0 && (

    - + {i18n(cfg.locale).components.recentNotes.seeRemainingMore({ remaining })}

    diff --git a/quartz/components/TagList.tsx b/quartz/components/TagList.tsx index c73ed392a..ad5a48a23 100644 --- a/quartz/components/TagList.tsx +++ b/quartz/components/TagList.tsx @@ -1,4 +1,4 @@ -import { FullSlug, resolveRelative } from "../util/path" +import { FullSlug, resolveRelative, getDisplaySlug } from "../util/path" import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" import { classNames } from "../util/lang" @@ -8,7 +8,7 @@ const TagList: QuartzComponent = ({ fileData, displayClass }: QuartzComponentPro return (