Jacky Zhao
2023-05-31 3636c052eb054d93a8a3ddfb9fdd873d5fe83a5d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { PluggableList } from "unified"
import { QuartzTransformerPlugin } from "../types"
import { remarkWikiLink } from "@flowershow/remark-wiki-link"
import { relative, relativeToRoot, slugify } from "../../path"
import path from "path"
import { visit } from 'unist-util-visit'
import isAbsoluteUrl from "is-absolute-url"
 
interface Options {
  /** How to resolve Markdown paths */
  markdownLinkResolution: 'absolute' | 'relative'
  /** Strips folders from a link so that it looks nice */
  prettyLinks: boolean
}
 
const defaultOptions: Options = {
  markdownLinkResolution: 'absolute',
  prettyLinks: true
}
 
export class LinkProcessing extends QuartzTransformerPlugin {
  name = "LinkProcessing"
  opts: Options
 
  constructor(opts?: Options) {
    super()
    this.opts = { ...defaultOptions, ...opts }
  }
 
  markdownPlugins(): PluggableList {
    return [[remarkWikiLink, {
      pathFormat: this.opts.markdownLinkResolution === "absolute" ? 'obsidian-absolute' : 'raw',
    }]]
  }
 
  htmlPlugins(): PluggableList {
    return [() => {
      return (tree, file) => {
        const curSlug = file.data.slug!
        const transformLink = (target: string) => {
          const targetSlug = slugify(decodeURI(target).trim())
          if (this.opts.markdownLinkResolution === 'relative' && !path.isAbsolute(targetSlug)) {
            return './' + relative(curSlug, targetSlug)
          } else {
            return './' + relativeToRoot(curSlug, targetSlug)
          }
        }
 
        visit(tree, 'element', (node, _index, _parent) => {
          // rewrite all links
          if (
            node.tagName === 'a' &&
            node.properties &&
            typeof node.properties.href === 'string'
          ) {
            node.properties.className = isAbsoluteUrl(node.properties.href) ? "external" : "internal"
 
            // don't process external links or intra-document anchors
            if (!(isAbsoluteUrl(node.properties.href) || node.properties.href.startsWith("#"))) {
              node.properties.href = transformLink(node.properties.href)
            }
 
            // rewrite link internals if prettylinks is on
            if (this.opts.prettyLinks && node.children.length === 1 && node.children[0].type === 'text') {
              node.children[0].value = path.basename(node.children[0].value)
            }
          }
 
          // transform all images
          if (
            node.tagName === 'img' &&
            node.properties &&
            typeof node.properties.src === 'string'
          ) {
            if (!isAbsoluteUrl(node.properties.src)) {
              const ext = path.extname(node.properties.src)
              node.properties.src = transformLink(path.join("assets", node.properties.src)) + ext
            }
          }
        })
      }
    }]
  }
}