From 5b6eb504587df592e42690743bce4b41d4066d00 Mon Sep 17 00:00:00 2001
From: "Thomas F. K. Jorna" <hello@tefkah.com>
Date: Sat, 13 Nov 2021 01:32:10 +0100
Subject: Feat: Markdown file previewing (#152)

* feat(md): initial support for md-roam

* feat(md): link support and more for md

* fix(md): add missing remark math package
---
 util/processOrg.tsx | 146 +++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 110 insertions(+), 36 deletions(-)

(limited to 'util/processOrg.tsx')

diff --git a/util/processOrg.tsx b/util/processOrg.tsx
index 84eb280..26d9377 100644
--- a/util/processOrg.tsx
+++ b/util/processOrg.tsx
@@ -12,16 +12,30 @@ import katex from 'rehype-katex'
 import 'katex/dist/katex.css'
 import rehype2react from 'rehype-react'
 
+import remarkParse from 'remark-parse'
+import remarkGFM from 'remark-gfm'
+// remark wikilinks does not have any type declarations
+//@ts-expect-error
+import remarkWikiLinks from 'remark-wiki-link'
+import remarkMath from 'remark-math'
+import remarkFrontMatter from 'remark-frontmatter'
+import remarkExtractFrontMatter from 'remark-extract-frontmatter'
+// remark sectionize does not have any type declarations
+//@ts-expect-error
+import remarkSectionize from 'remark-sectionize'
+import remarkRehype from 'remark-rehype'
+
 import { PreviewLink } from '../components/Sidebar/Link'
-import { NodeByCite, NodeById } from '../pages'
+import { LinksByNodeId, NodeByCite, NodeById, normalizeLinkEnds } from '../pages'
 import React, { createContext, ReactNode, useMemo } from 'react'
 import { OrgImage } from '../components/Sidebar/OrgImage'
 import { Section } from '../components/Sidebar/Section'
 import { NoteContext } from './NoteContext'
+import { OrgRoamLink, OrgRoamNode } from '../api'
 
 export interface ProcessedOrgProps {
   nodeById: NodeById
-  previewNode: any
+  previewNode: OrgRoamNode
   setPreviewNode: any
   previewText: any
   nodeByCite: NodeByCite
@@ -29,6 +43,7 @@ export interface ProcessedOrgProps {
   openContextMenu: any
   outline: boolean
   collapse: boolean
+  linksByNodeId: LinksByNodeId
 }
 
 export const ProcessedOrg = (props: ProcessedOrgProps) => {
@@ -42,52 +57,111 @@ export const ProcessedOrg = (props: ProcessedOrgProps) => {
     openContextMenu,
     outline,
     collapse,
+    linksByNodeId,
   } = props
+  console.log(linksByNodeId)
+  console.log(previewNode)
+  if (!previewNode || !linksByNodeId) {
+    return null
+  }
 
-  const processor = unified()
+  const orgProcessor = unified()
     .use(uniorgParse)
     .use(extractKeywords)
     .use(attachments)
     .use(uniorgSlug)
     .use(uniorg2rehype, { useSections: true })
-    //.data('settings', { fragment: true })
-    // .use(highlight)
-    .use(katex)
-    .use(rehype2react, {
-      createElement: React.createElement,
-      // eslint-disable-next-line react/display-name
-      components: {
-        a: ({ children, href }) => {
-          return (
-            <PreviewLink
-              nodeByCite={nodeByCite}
-              setSidebarHighlightedNode={setSidebarHighlightedNode}
-              href={`${href as string}`}
-              nodeById={nodeById}
-              setPreviewNode={setPreviewNode}
-              openContextMenu={openContextMenu}
-              outline={outline}
-            >
+
+  const nodesInNote =
+    linksByNodeId[previewNode?.id!]?.reduce((acc: NodeById, link: OrgRoamLink) => {
+      const links = normalizeLinkEnds(link)
+      const relevantLink = links.filter((l) => l !== previewNode.id).join('')
+      return {
+        ...acc,
+        [relevantLink]: nodeById[relevantLink],
+      }
+    }, {}) || {}
+
+  const linkEntries = Object.entries(nodesInNote)
+  const wikiLinkResolver = (wikiLink: string): string[] => {
+    const entry = linkEntries.find((idNodeArray) => {
+      console.log(idNodeArray)
+      console.log(wikiLink)
+      return idNodeArray?.[1]?.title === wikiLink
+    })
+    const id = entry?.[0] ?? ''
+    return [id]
+  }
+
+  const wikiLinkProcessor = (wikiLink: string): string => {
+    console.log(wikiLink)
+    return `id:${wikiLink}`
+  }
+
+  const mdProcessor = unified()
+    .use(remarkParse)
+    .use(remarkFrontMatter, ['yaml'])
+    .use(remarkExtractFrontMatter)
+    .use(remarkWikiLinks, {
+      permaLinks: Object.keys(nodesInNote),
+      pageResolver: wikiLinkResolver,
+      hrefTemplate: wikiLinkProcessor,
+    })
+    .use(remarkSectionize)
+    .use(remarkMath)
+    .use(remarkGFM)
+    .use(remarkRehype)
+  //.data('settings', { fragment: true })
+  // .use(highlight)
+
+  const isMarkdown = previewNode?.file?.slice(-3) === '.md'
+  const baseProcessor = isMarkdown ? mdProcessor : orgProcessor
+
+  const processor = useMemo(
+    () =>
+      baseProcessor.use(katex).use(rehype2react, {
+        createElement: React.createElement,
+        // eslint-disable-next-line react/display-name
+        components: {
+          a: ({ children, href }) => {
+            return (
+              <PreviewLink
+                nodeByCite={nodeByCite}
+                setSidebarHighlightedNode={setSidebarHighlightedNode}
+                href={`${href as string}`}
+                nodeById={nodeById}
+                linksByNodeId={linksByNodeId}
+                setPreviewNode={setPreviewNode}
+                openContextMenu={openContextMenu}
+                outline={outline}
+                previewNode={previewNode}
+                isWiki={isMarkdown}
+              >
+                {children}
+              </PreviewLink>
+            )
+          },
+          img: ({ src }) => {
+            return <OrgImage src={src as string} file={previewNode?.file} />
+          },
+          section: ({ children, className }) => (
+            <Section {...{ outline, collapse }} className={className as string}>
               {children}
-            </PreviewLink>
-          )
-        },
-        img: ({ src }) => {
-          return <OrgImage src={src as string} file={previewNode?.file} />
-        },
-        section: ({ children, className }) => (
-          <Section {...{ outline, collapse }} className={className as string}>
-            {children}
-          </Section>
-        ),
-        p: ({ children }) => {
-          return <p lang="en">{children as ReactNode}</p>
+            </Section>
+          ),
+          p: ({ children }) => {
+            return <p lang="en">{children as ReactNode}</p>
+          },
         },
-      },
-    })
+      }),
+    [previewNode?.id],
+  )
 
   const text = useMemo(() => processor.processSync(previewText).result, [previewText])
   return (
     <NoteContext.Provider value={{ collapse, outline }}>{text as ReactNode}</NoteContext.Provider>
   )
 }
+function useCallBack(arg0: () => unified.Processor<unified.Settings>) {
+  throw new Error('Function not implemented.')
+}
-- 
cgit v1.2.3

