fix(alias): Fix permalink and alias resolution

This commit is contained in:
Emile Bangma 2025-03-04 14:22:18 +00:00
parent b050162f82
commit 6ffbd905fb
3 changed files with 25 additions and 14 deletions

View File

@ -2,6 +2,10 @@
title: AliasRedirects title: AliasRedirects
tags: tags:
- plugin/emitter - plugin/emitter
permalink: "permalink"
alias:
- "alias"
- "aliases"
--- ---
This plugin emits HTML redirect pages for aliases and permalinks defined in the frontmatter of content files. This plugin emits HTML redirect pages for aliases and permalinks defined in the frontmatter of content files.
@ -11,14 +15,15 @@ For example, A `foo.md` has the following frontmatter
```md title="foo.md" ```md title="foo.md"
--- ---
title: "Foo" title: "Foo"
permalink: "bar"
alias: alias:
- "bar" - "baz"
--- ---
``` ```
The target `host.me/bar` will be redirected to `host.me/foo` The target `host.me/bar` and `host.me/baz` will be redirected to `host.me/foo`
Note that these are permanent redirect. Note that these are permanent redirects.
The emitter supports the following aliases: The emitter supports the following aliases:

View File

@ -1,4 +1,4 @@
import { FilePath, joinSegments, resolveRelative, simplifySlug } from "../../util/path" import { FilePath, joinSegments, simplifySlug, FullSlug } from "../../util/path"
import { QuartzEmitterPlugin } from "../types" import { QuartzEmitterPlugin } from "../types"
import { write } from "./helpers" import { write } from "./helpers"
import DepGraph from "../../depgraph" import DepGraph from "../../depgraph"
@ -28,8 +28,11 @@ export const AliasRedirects: QuartzEmitterPlugin = () => ({
for (const [_tree, file] of content) { for (const [_tree, file] of content) {
const ogSlug = simplifySlug(file.data.slug!) const ogSlug = simplifySlug(file.data.slug!)
for (const slug of file.data.aliases ?? []) { const slugs = [file.data.frontmatter?.permalink || [], ...(file.data.aliases || [])]
const redirUrl = resolveRelative(slug, file.data.slug!)
for (const slug of slugs ?? []) {
if (typeof slug !== "string") continue
const redirUrl = file.data.slug!
const fp = await write({ const fp = await write({
ctx, ctx,
content: ` content: `
@ -44,7 +47,7 @@ export const AliasRedirects: QuartzEmitterPlugin = () => ({
</head> </head>
</html> </html>
`, `,
slug, slug: slug as FullSlug,
ext: ".html", ext: ".html",
}) })

View File

@ -3,12 +3,11 @@ import remarkFrontmatter from "remark-frontmatter"
import { QuartzTransformerPlugin } from "../types" import { QuartzTransformerPlugin } from "../types"
import yaml from "js-yaml" import yaml from "js-yaml"
import toml from "toml" import toml from "toml"
import { FilePath, FullSlug, joinSegments, slugifyFilePath, slugTag } from "../../util/path" import { FullSlug, joinSegments, slugTag } from "../../util/path"
import { QuartzPluginData } from "../vfile" import { QuartzPluginData } from "../vfile"
import { i18n } from "../../i18n" import { i18n } from "../../i18n"
import { Argv } from "../../util/ctx" import { Argv } from "../../util/ctx"
import { VFile } from "vfile" import { VFile } from "vfile"
import path from "path"
export interface Options { export interface Options {
delimiters: string | [string, string] delimiters: string | [string, string]
@ -22,7 +21,10 @@ const defaultOptions: Options = {
function coalesceAliases(data: { [key: string]: any }, aliases: string[]) { function coalesceAliases(data: { [key: string]: any }, aliases: string[]) {
for (const alias of aliases) { for (const alias of aliases) {
if (data[alias] !== undefined && data[alias] !== null) return data[alias] if (data[alias] !== undefined && data[alias] !== null) {
if (typeof data[alias] === "string") return [data[alias]]
return data[alias]
}
} }
} }
@ -43,14 +45,14 @@ function coerceToArray(input: string | string[]): string[] | undefined {
.map((tag: string | number) => tag.toString()) .map((tag: string | number) => tag.toString())
} }
export function getAliasSlugs(aliases: string[], argv: Argv, file: VFile): FullSlug[] { export function getAliasSlugs(aliases: string[], _argv: Argv, file: VFile): FullSlug[] {
const dir = path.posix.relative(argv.directory, path.dirname(file.data.filePath!))
const slugs: FullSlug[] = aliases.map( const slugs: FullSlug[] = aliases.map(
(alias) => path.posix.join(dir, slugifyFilePath(alias as FilePath)) as FullSlug, (alias) => (alias.startsWith("/") ? alias : `/${alias}`) as FullSlug,
) )
const permalink = file.data.frontmatter?.permalink const permalink = file.data.frontmatter?.permalink
if (typeof permalink === "string") { if (typeof permalink === "string") {
slugs.push(permalink as FullSlug) const absolutePermalink = permalink.startsWith("?") ? permalink : `/${permalink}`
slugs.push(absolutePermalink as FullSlug)
} }
// fix any slugs that have trailing slash // fix any slugs that have trailing slash
return slugs.map((slug) => return slugs.map((slug) =>
@ -130,6 +132,7 @@ declare module "vfile" {
created: string created: string
published: string published: string
description: string description: string
permalink: string
publish: boolean | string publish: boolean | string
draft: boolean | string draft: boolean | string
lang: string lang: string