diff --git a/quartz/plugins/transformers/ofm.ts b/quartz/plugins/transformers/ofm.ts index 4c6a6dbe..b6d158c7 100644 --- a/quartz/plugins/transformers/ofm.ts +++ b/quartz/plugins/transformers/ofm.ts @@ -121,9 +121,9 @@ const calloutRegex = new RegExp(/^\[\!(\w+)\]([+-]?)/) const calloutLineRegex = new RegExp(/^> *\[\!\w+\][+-]?.*$/, "gm") // (?:^| ) -> non-capturing group, tag should start be separated by a space or be the start of the line // #(...) -> capturing group, tag itself must start with # -// (?:[-_\p{L}])+ -> non-capturing group, non-empty string of (Unicode-aware) alpha-numeric characters, hyphens and/or underscores -// (?:\/[-_\p{L}]+)*) -> non-capturing group, matches an arbitrary number of tag strings separated by "/" -const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\d])+(?:\/[-_\p{L}\d]+)*)/, "gu") +// (?:[-_\p{L}\d\p{Z}])+ -> non-capturing group, non-empty string of (Unicode-aware) alpha-numeric characters and symbols, hyphens and/or underscores +// (?:\/[-_\p{L}\d\p{Z}]+)*) -> non-capturing group, matches an arbitrary number of tag strings separated by "/" +const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\d\p{Z}])+(?:\/[-_\p{L}\d\p{Z}]+)*)/, "gu") const blockReferenceRegex = new RegExp(/\^([A-Za-z0-9]+)$/, "g") export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin | undefined> = ( @@ -405,6 +405,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin if (/^\d+$/.test(tag)) { return false } + tag = slugTag(tag) if (file.data.frontmatter && !file.data.frontmatter.tags.includes(tag)) { file.data.frontmatter.tags.push(tag) diff --git a/quartz/util/path.ts b/quartz/util/path.ts index 5cf54b80..92cfabe4 100644 --- a/quartz/util/path.ts +++ b/quartz/util/path.ts @@ -1,4 +1,4 @@ -import { slug } from "github-slugger" +import { slug as slugAnchor } from "github-slugger" import type { Element as HastElement } from "hast" // this file must be isomorphic so it can't use node libs (e.g. path) @@ -43,6 +43,14 @@ export function getFullSlug(window: Window): FullSlug { return res } +function sluggify(s: string): string { + return s + .split("/") + .map((segment) => segment.replace(/\s/g, "-").replace(/%/g, "-percent").replace(/\?/g, "-q")) // slugify all segments + .join("/") // always use / as sep + .replace(/\/$/, "") +} + export function slugifyFilePath(fp: FilePath, excludeExt?: boolean): FullSlug { fp = _stripSlashes(fp) as FilePath let ext = _getFileExtension(fp) @@ -51,11 +59,7 @@ export function slugifyFilePath(fp: FilePath, excludeExt?: boolean): FullSlug { ext = "" } - let slug = withoutFileExt - .split("/") - .map((segment) => segment.replace(/\s/g, "-").replace(/%/g, "-percent").replace(/\?/g, "-q")) // slugify all segments - .join("/") // always use / as sep - .replace(/\/$/, "") // remove trailing slash + let slug = sluggify(withoutFileExt) // treat _index as index if (_endsWith(slug, "_index")) { @@ -156,14 +160,10 @@ export function splitAnchor(link: string): [string, string] { return [fp, anchor] } -export function slugAnchor(anchor: string) { - return slug(anchor) -} - export function slugTag(tag: string) { return tag .split("/") - .map((tagSegment) => slug(tagSegment)) + .map((tagSegment) => sluggify(tagSegment)) .join("/") }