From 5599eb590e1b9163d41847153545764ed9b02ff6 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 23 Jul 2023 14:02:57 -0700 Subject: [PATCH] feat: process tags in content --- content/features/upcoming features.md | 6 +--- quartz/components/TagList.tsx | 4 +-- quartz/plugins/transformers/links.ts | 3 +- quartz/plugins/transformers/ofm.ts | 48 ++++++++++++++++++++------- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/content/features/upcoming features.md b/content/features/upcoming features.md index 5cb7b972..de168806 100644 --- a/content/features/upcoming features.md +++ b/content/features/upcoming features.md @@ -2,7 +2,6 @@ draft: true --- -- parse tags in content - breadcrumbs component - filetree component - recent notes component @@ -10,10 +9,7 @@ draft: true - [https://giscus.app/](https://giscus.app/) extension - custom md blocks (e.g. for poetry) - sidenotes? [https://github.com/capnfabs/paperesque](https://github.com/capnfabs/paperesque) -- watch mode - - watch for markdown changes and quartz config changes - - markdown changes only involve processing that single markdown file (at least for parsing) and then rerunning the filter and emitters - - config changes rebuild the whole thing +- watch mode for config/source code - direct match in search using double quotes - attachments path - [https://help.obsidian.md/Advanced+topics/Using+Obsidian+URI](https://help.obsidian.md/Advanced+topics/Using+Obsidian+URI) diff --git a/quartz/components/TagList.tsx b/quartz/components/TagList.tsx index c36b0a28..8b909557 100644 --- a/quartz/components/TagList.tsx +++ b/quartz/components/TagList.tsx @@ -14,7 +14,7 @@ function TagList({ fileData }: QuartzComponentProps) { const linkDest = baseDir + `/tags/${slugAnchor(tag)}` return (
  • - + {display}
  • @@ -42,7 +42,7 @@ TagList.css = ` overflow-wrap: normal; } -.tags > li > a { +a.tag-link { border-radius: 8px; background-color: var(--highlight); padding: 0.2rem 0.5rem; diff --git a/quartz/plugins/transformers/links.ts b/quartz/plugins/transformers/links.ts index 96c5f589..e496171e 100644 --- a/quartz/plugins/transformers/links.ts +++ b/quartz/plugins/transformers/links.ts @@ -72,7 +72,8 @@ export const CrawlLinks: QuartzTransformerPlugin | undefined> = typeof node.properties.href === "string" ) { let dest = node.properties.href as RelativeURL - node.properties.className = isAbsoluteUrl(dest) ? "external" : "internal" + node.properties.className ??= [] + node.properties.className.push(isAbsoluteUrl(dest) ? "external" : "internal") // don't process external links or intra-document anchors if (!(isAbsoluteUrl(dest) || dest.startsWith("#"))) { diff --git a/quartz/plugins/transformers/ofm.ts b/quartz/plugins/transformers/ofm.ts index 23b14019..6b68fcc2 100644 --- a/quartz/plugins/transformers/ofm.ts +++ b/quartz/plugins/transformers/ofm.ts @@ -9,7 +9,7 @@ import path from "path" import { JSResource } from "../../resources" // @ts-ignore import calloutScript from "../../components/scripts/callout.inline.ts" -import { FilePath, slugifyFilePath } from "../../path" +import { FilePath, canonicalizeServer, pathToRoot, slugifyFilePath } from "../../path" export interface Options { comments: boolean @@ -17,6 +17,7 @@ export interface Options { wikilinks: boolean callouts: boolean mermaid: boolean + parseTags: boolean } const defaultOptions: Options = { @@ -25,6 +26,7 @@ const defaultOptions: Options = { wikilinks: true, callouts: true, mermaid: true, + parseTags: true, } const icons = { @@ -97,22 +99,19 @@ const capitalize = (s: string): string => { return s.substring(0, 1).toUpperCase() + s.substring(1) } -// Match wikilinks // !? -> optional embedding // \[\[ -> open brace // ([^\[\]\|\#]+) -> one or more non-special characters ([,],|, or #) (name) // (#[^\[\]\|\#]+)? -> # then one or more non-special characters (heading link) // (|[^\[\]\|\#]+)? -> | then one or more non-special characters (alias) const wikilinkRegex = new RegExp(/!?\[\[([^\[\]\|\#]+)(#[^\[\]\|\#]+)?(\|[^\[\]\|\#]+)?\]\]/, "g") - -// Match highlights const highlightRegex = new RegExp(/==(.+)==/, "g") - -// Match comments const commentRegex = new RegExp(/%%(.+)%%/, "g") - // from https://github.com/escwxyz/remark-obsidian-callout/blob/main/src/index.ts const calloutRegex = new RegExp(/^\[\!(\w+)\]([+-]?)/) +// (?:^| ) -> non-capturing group, tag should start be separated by a space or be the start of the line +// #(\w+) -> tag itself is # followed by a string of alpha-numeric characters +const tagRegex = new RegExp(/(?:^| )#(\w+)/, "g") export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin | undefined> = ( userOpts, @@ -226,7 +225,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin findAndReplace(tree, commentRegex, (_value: string, ..._capture: string[]) => { return { type: "text", - value: "", + value: "" } }) } @@ -297,9 +296,8 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin node.data = { hProperties: { ...(node.data?.hProperties ?? {}), - className: `callout ${collapse ? "is-collapsible" : ""} ${ - defaultState === "collapsed" ? "is-collapsed" : "" - }`, + className: `callout ${collapse ? "is-collapsible" : ""} ${defaultState === "collapsed" ? "is-collapsed" : "" + }`, "data-callout": calloutType, "data-callout-fold": collapse, }, @@ -317,7 +315,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin if (node.lang === "mermaid") { node.data = { hProperties: { - className: "mermaid", + className: ["mermaid"], }, } } @@ -326,6 +324,32 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin }) } + if (opts.parseTags) { + plugins.push(() => { + return (tree: Root, file) => { + const slug = canonicalizeServer(file.data.slug!) + const base = pathToRoot(slug) + findAndReplace(tree, tagRegex, (value: string, tag: string) => { + return { + type: "link", + url: base + `/tags/${slugAnchor(tag)}`, + data: { + hProperties: { + className: ["tag-link"], + }, + }, + children: [ + { + type: "text", + value, + }, + ], + } + }) + } + }) + } + return plugins }, htmlPlugins() {