From 352075ae81a3304a7bfa2512ef69b1cdacb26c12 Mon Sep 17 00:00:00 2001
From: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Mon, 12 Jun 2023 06:26:43 +0000
Subject: [PATCH] refactor plugins to be functions instead of classes

---
 quartz/plugins/transformers/ofm.ts |  280 +++++++++++++++++++++++++++----------------------------
 1 files changed, 137 insertions(+), 143 deletions(-)

diff --git a/quartz/plugins/transformers/ofm.ts b/quartz/plugins/transformers/ofm.ts
index 23ed37c..1733b94 100644
--- a/quartz/plugins/transformers/ofm.ts
+++ b/quartz/plugins/transformers/ofm.ts
@@ -89,174 +89,168 @@
   return s.substring(0, 1).toUpperCase() + s.substring(1);
 }
 
-export class ObsidianFlavoredMarkdown extends QuartzTransformerPlugin {
-  name = "ObsidianFlavoredMarkdown"
-  opts: Options
+export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options> | undefined> = (userOpts) => {
+  const opts = { ...defaultOptions, ...userOpts }
+  return {
+    name: "ObsidianFlavoredMarkdown",
+    markdownPlugins() {
+      const plugins: PluggableList = []
+      if (opts.wikilinks) {
+        plugins.push(() => {
+          // 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 backlinkRegex = new RegExp(/!?\[\[([^\[\]\|\#]+)(#[^\[\]\|\#]+)?(\|[^\[\]\|\#]+)?\]\]/, "g")
+          return (tree: Root, _file) => {
+            findAndReplace(tree, backlinkRegex, (value: string, ...capture: string[]) => {
+              const [fp, rawHeader, rawAlias] = capture
+              const anchor = rawHeader?.trim() ?? ""
+              const alias = rawAlias?.slice(1).trim()
 
-  constructor(opts?: Partial<Options>) {
-    super()
-    this.opts = { ...defaultOptions, ...opts }
-  }
-
-  markdownPlugins(): PluggableList {
-    const plugins: PluggableList = []
-
-    if (this.opts.wikilinks) {
-      plugins.push(() => {
-        // 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 backlinkRegex = new RegExp(/!?\[\[([^\[\]\|\#]+)(#[^\[\]\|\#]+)?(\|[^\[\]\|\#]+)?\]\]/, "g")
-        return (tree: Root, _file) => {
-          findAndReplace(tree, backlinkRegex, (value: string, ...capture: string[]) => {
-            const [fp, rawHeader, rawAlias] = capture
-            const anchor = rawHeader?.trim() ?? ""
-            const alias = rawAlias?.slice(1).trim()
-
-            // embed cases
-            if (value.startsWith("!")) {
-              const ext = path.extname(fp).toLowerCase()
-              const url = slugify(fp.trim()) + ext
-              if ([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg"].includes(ext)) {
-                const dims = alias ?? ""
-                let [width, height] = dims.split("x", 2)
-                width ||= "auto"
-                height ||= "auto"
-                return {
-                  type: 'image',
-                  url,
-                  data: {
-                    hProperties: {
-                      width, height
+              // embed cases
+              if (value.startsWith("!")) {
+                const ext = path.extname(fp).toLowerCase()
+                const url = slugify(fp.trim()) + ext
+                if ([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg"].includes(ext)) {
+                  const dims = alias ?? ""
+                  let [width, height] = dims.split("x", 2)
+                  width ||= "auto"
+                  height ||= "auto"
+                  return {
+                    type: 'image',
+                    url,
+                    data: {
+                      hProperties: {
+                        width, height
+                      }
                     }
                   }
+                } else if ([".mp4", ".webm", ".ogv", ".mov", ".mkv"].includes(ext)) {
+                  return {
+                    type: 'html',
+                    value: `<video src="${url}" controls></video>`
+                  }
+                } else if ([".mp3", ".webm", ".wav", ".m4a", ".ogg", ".3gp", ".flac"].includes(ext)) {
+                  return {
+                    type: 'html',
+                    value: `<audio src="${url}" controls></audio>`
+                  }
+                } else if ([".pdf"].includes(ext)) {
+                  return {
+                    type: 'html',
+                    value: `<iframe src="${url}"></iframe>`
+                  }
                 }
-              } else if ([".mp4", ".webm", ".ogv", ".mov", ".mkv"].includes(ext)) {
-                return {
-                  type: 'html',
-                  value: `<video src="${url}" controls></video>`
-                }
-              } else if ([".mp3", ".webm", ".wav", ".m4a", ".ogg", ".3gp", ".flac"].includes(ext)) {
-                return {
-                  type: 'html',
-                  value: `<audio src="${url}" controls></audio>`
-                }
-              } else if ([".pdf"].includes(ext)) {
-                return {
-                  type: 'html',
-                  value: `<iframe src="${url}"></iframe>`
-                }
+                // otherwise, fall through to regular link
               }
-              // otherwise, fall through to regular link
-            }
 
-            // internal link
-            const url = slugify(fp.trim() + anchor)
-            return {
-              type: 'link',
-              url,
-              children: [{
-                type: 'text',
-                value: alias ?? fp
-              }]
-            }
-          })
+              // internal link
+              const url = slugify(fp.trim() + anchor)
+              return {
+                type: 'link',
+                url,
+                children: [{
+                  type: 'text',
+                  value: alias ?? fp
+                }]
+              }
+            })
+          }
         }
+        )
       }
-      )
-    }
 
-    if (this.opts.highlight) {
-      plugins.push(() => {
-        // Match highlights 
-        const highlightRegex = new RegExp(/==(.+)==/, "g")
-        return (tree: Root, _file) => {
-          findAndReplace(tree, highlightRegex, (_value: string, ...capture: string[]) => {
-            const [inner] = capture
-            return {
-              type: 'html',
-              value: `<span class="text-highlight">${inner}</span>`
-            }
-          })
-        }
-      })
-    }
+      if (opts.highlight) {
+        plugins.push(() => {
+          // Match highlights 
+          const highlightRegex = new RegExp(/==(.+)==/, "g")
+          return (tree: Root, _file) => {
+            findAndReplace(tree, highlightRegex, (_value: string, ...capture: string[]) => {
+              const [inner] = capture
+              return {
+                type: 'html',
+                value: `<span class="text-highlight">${inner}</span>`
+              }
+            })
+          }
+        })
+      }
 
-    if (this.opts.callouts) {
-      plugins.push(() => {
-        // from https://github.com/escwxyz/remark-obsidian-callout/blob/main/src/index.ts
-        const calloutRegex = new RegExp(/^\[\!(\w+)\]([+-]?)/)
-        return (tree: Root, _file) => {
-          visit(tree, "blockquote", (node) => {
-            if (node.children.length === 0) {
-              return
-            }
+      if (opts.callouts) {
+        plugins.push(() => {
+          // from https://github.com/escwxyz/remark-obsidian-callout/blob/main/src/index.ts
+          const calloutRegex = new RegExp(/^\[\!(\w+)\]([+-]?)/)
+          return (tree: Root, _file) => {
+            visit(tree, "blockquote", (node) => {
+              if (node.children.length === 0) {
+                return
+              }
 
-            // find first line
-            const firstChild = node.children[0]
-            if (firstChild.type !== "paragraph" || firstChild.children[0]?.type !== "text") {
-              return
-            }
+              // find first line
+              const firstChild = node.children[0]
+              if (firstChild.type !== "paragraph" || firstChild.children[0]?.type !== "text") {
+                return
+              }
 
-            const text = firstChild.children[0].value
-            const [firstLine, ...remainingLines] = text.split("\n")
-            const remainingText = remainingLines.join("\n")
+              const text = firstChild.children[0].value
+              const [firstLine, ...remainingLines] = text.split("\n")
+              const remainingText = remainingLines.join("\n")
 
-            const match = firstLine.match(calloutRegex)
-            if (match && match.input) {
-              const [calloutDirective, typeString, collapseChar] = match
-              const calloutType = typeString.toLowerCase() as keyof typeof callouts
-              const collapse = collapseChar === "+" || collapseChar === "-"
-              const defaultState = collapseChar === "-" ? "collapsed" : "expanded"
-              const title = match.input.slice(calloutDirective.length).trim() || capitalize(calloutType)
+              const match = firstLine.match(calloutRegex)
+              if (match && match.input) {
+                const [calloutDirective, typeString, collapseChar] = match
+                const calloutType = typeString.toLowerCase() as keyof typeof callouts
+                const collapse = collapseChar === "+" || collapseChar === "-"
+                const defaultState = collapseChar === "-" ? "collapsed" : "expanded"
+                const title = match.input.slice(calloutDirective.length).trim() || capitalize(calloutType)
 
-              const titleNode: HTML = {
-                type: "html",
-                value: `<div 
+                const titleNode: HTML = {
+                  type: "html",
+                  value: `<div 
                   class="callout-title"
                 >
                   <div class="callout-icon">${callouts[canonicalizeCallout(calloutType)]}</div>
                   <div class="callout-title-inner">${title}</div>
                 </div>`
-              }
+                }
 
-              const blockquoteContent: (BlockContent | DefinitionContent)[] = [titleNode]
-              if (remainingText.length > 0) {
-                blockquoteContent.push({
-                  type: 'paragraph',
-                  children: [{
-                    type: 'text',
-                    value: remainingText,
-                  }]
+                const blockquoteContent: (BlockContent | DefinitionContent)[] = [titleNode]
+                if (remainingText.length > 0) {
+                  blockquoteContent.push({
+                    type: 'paragraph',
+                    children: [{
+                      type: 'text',
+                      value: remainingText,
+                    }]
 
-                })
-              }
+                  })
+                }
 
-              // replace first line of blockquote with title and rest of the paragraph text
-              node.children.splice(0, 1, ...blockquoteContent)
+                // replace first line of blockquote with title and rest of the paragraph text
+                node.children.splice(0, 1, ...blockquoteContent)
 
-              // add properties to base blockquote
-              node.data = {
-                hProperties: {
-                  ...(node.data?.hProperties ?? {}),
-                  className: `callout ${collapse ? "is-collapsible" : ""} ${defaultState === "collapsed" ? "is-collapsed" : ""}`,
-                  "data-callout": calloutType,
-                  "data-callout-fold": collapse,
+                // add properties to base blockquote
+                node.data = {
+                  hProperties: {
+                    ...(node.data?.hProperties ?? {}),
+                    className: `callout ${collapse ? "is-collapsible" : ""} ${defaultState === "collapsed" ? "is-collapsed" : ""}`,
+                    "data-callout": calloutType,
+                    "data-callout-fold": collapse,
+                  }
                 }
               }
-            }
-          })
-        }
-      })
+            })
+          }
+        })
+      }
+      return plugins
+    },
+
+    htmlPlugins() {
+      return [rehypeRaw]
     }
-
-    return plugins
-  }
-
-  htmlPlugins(): PluggableList {
-    return [rehypeRaw]
   }
 }

--
Gitblit v1.10.0