50 - garden-astro - Add image & link support

Normal Image looks like this in Obsidian, it’s a markdown image link.

![](1-Projects/100DaysOfCode-R3/attachments/Pasted%20image%2020230628232312.png)

^ If you see the images above rendered correctly, the Remark plugin is working.

It is an absolute path from the root folder, so to make it render on Astro I have to copy the image to Astro, and also modify the resulting link to /public/path-to-image, I plan to create a Remark plugin to modify the image & href links.

The plugin itself is a tree traversal function that recursively visit each node and modify the url of images like so

function prependImageSrcPlugin() {
  return (tree) => {
    function visit(node) {
      if (node.type === "image" && node.url) {
        node.url = `/images/${node.url}`
      }
      if (node.children) {
        node.children.forEach(visit)
      }
    }

    visit(tree)
  }
}

export default defineConfig({
  markdown: {
    remarkPlugins: [prependImageSrcPlugin],
  },
})

Then add the script to copy the images from Obsidian to Astro build step, by extracting image path of each markdown file, and copy to /public/images/ folder

export const extractImageSources = (filePath) => {
  const markdown = fs.readFileSync(filePath, "utf-8")

  const imageSources = []

  const processor = remark().use(() => (tree) => {
    visit(tree, "image", (node) => {
      // Decode URI since the url can have spaces or other symbols `%20`
      const imageUrl = decodeURI(node.url)

      imageSources.push(imageUrl)
    })
  })

  processor.processSync(markdown)

  return imageSources
}

// Usage
const imageSources = extractImageSources(filePath)

imageSources.forEach((imageSource) => {
    const srcPath = `/your/obsidian/path/${imageSource}`
    
    const destinationPath = `./public/images/${imageSource}`
    const destinationDir = path.dirname(destinationPath)
    
    // Create the destination directory if it doesn't exist
    if (!fs.existsSync(destinationDir)) {
      fs.mkdirSync(destinationDir, { recursive: true })
    }
    
    copyFileSync(srcPath, destinationPath)
    
    console.log("Copied", srcPath, "to", destinationPath)
})