Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help with rendering images within ObsidianVault #190

Closed
exosyphon opened this issue Jul 1, 2024 · 12 comments
Closed

Help with rendering images within ObsidianVault #190

exosyphon opened this issue Jul 1, 2024 · 12 comments

Comments

@exosyphon
Copy link

Hi, thank you for all your work in getting images inside of Neovim. I am really excited to try and get this working.

I am able to use the minimal setup and also configured my setup to work with this style image:

This is a remote image

Inside of my ObsidianVault, I have an Attachments folder at the root where all of my images are stored.

How can I configure image.nvim to look in this directory when it sees something like this?

![[Test.png]]

I am probably missing something obvious or unsure how to configure resolve_image_path to make this work.

Thank you again for your time and work on this plugin!

@3rd
Copy link
Owner

3rd commented Jul 1, 2024

Hey, we could probably add a hook for the Markdown integration, it must be trying to load the image from the same directory as the document when it should search for it in a special place. You can patch it in the markdown integration meanwhile.

@exosyphon
Copy link
Author

Will do. Here's what I have hard coded and got it to render correctly.

          elseif current_image and key == "url" then
            current_image.url = "~/Documents/ObsidianVault/Attachments/" .. value
            table.insert(images, current_image)
            current_image = nil
          end

@xamcost
Copy link

xamcost commented Sep 27, 2024

@exosyphon In case that helps, you can use the resolve_image_path parameter in your config for this:

          resolve_image_path = function(document_path, image_path, fallback)
            local working_dir = vim.fn.getcwd()
            -- Format image path for Obsidian notes
            if (working_dir:find("path/to/your/vault")) then
              return working_dir .. "/" .. image_path
            end
            -- Fallback to the default behavior
            return fallback(document_path, image_path)
          end,

@lkschu
Copy link

lkschu commented Nov 17, 2024

@exosyphon In case that helps, you can use the resolve_image_path parameter in your config for this:

          resolve_image_path = function(document_path, image_path, fallback)
            local working_dir = vim.fn.getcwd()
            -- Format image path for Obsidian notes
            if (working_dir:find("path/to/your/vault")) then
              return working_dir .. "/" .. image_path
            end
            -- Fallback to the default behavior
            return fallback(document_path, image_path)
          end,

This is very helpful! One addition: find has an optional flag for the start position and a flag whether the string should be interpreted literally. The latter is important, so vault paths like obsidian-vault are detected. So change the line to this:

            if (working_dir:find("path/to/match",1,true)) then

LazyStability added a commit to LazyStability/kickstart.nvim that referenced this issue Nov 17, 2024
Does work if the file is in the same directory
Does not work yet for obsidian vaults
3rd/image.nvim#190
@ahmedelgabri
Copy link

I'm having a problem getting this to work. The return paths are correct, but the plugin is not rendering any images.

resolve_image_path = function(document_path, image_path, fallback)
	local working_dir = vim.fn.getcwd()
	local notes_dir = vim.fn.expand(vim.env.NOTES_DIR)
	-- Format image path for Obsidian notes
	if working_dir:find(notes_dir, 1, true) then
		return vim.fn.shellescape(notes_dir .. '/' .. image_path)
	end
	-- Fallback to the default behavior
	return fallback(document_path, image_path)
end,

Here is an example doc:

File: $NOTES_DIR/folder/something.md

![[assets/something/hashmd5.png]]

image_path -> assets/something/hashmd5.png

The returned value from the resolve_image_path is correct: '/Users/ahmedelgabri/notes/assets/something/hashmd5.png'

If I run file '/Users/ahmedelgabri/notes/assets/something/hashmd5.png' I get this, so the image exists on disk which means the path is correct.

/Users/ahmedelgabri/notes/assets/something/hashmd5.png: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 5170x2802, components 3

But I don't see any previews, if I go an open a different .md file outside of the notes path, for example a README.md inside a repo, I can see image previews just fine.

LazyStability added a commit to LazyStability/kickstart.nvim that referenced this issue Nov 21, 2024
Does work if the file is in the same directory
Does not work yet for obsidian vaults
3rd/image.nvim#190
@ficcdaf
Copy link

ficcdaf commented Dec 3, 2024

@ahmedelgabri I investigated your problem a bit. I had to slightly modify your function to set the environment variable to my own Obsidian path:

  vim.env.NOTES_DIR = "/home/fic/second-brain"

I was able to fix your function by removing the call to vim.fn.shellescape. In case it matter, I am on Linux. Please try the following:

local function resolver_ahmed_fixed(document_path, image_path, fallback)
  -- I had to set my own vault root, but you
  -- shouldn't need this line yourself 
  -- vim.env.NOTES_DIR = "/home/fic/second-brain"
  local working_dir = vim.fn.getcwd()
  local notes_dir = vim.fn.expand(vim.env.NOTES_DIR)
  -- Format image path for Obsidian notes
  if working_dir:find(notes_dir, 1, true) then
    return (notes_dir .. "/" .. image_path)
  end
  -- Fallback to the default behavior
  return fallback(document_path, image_path)
end

With this I was able to get your function to work with the environment variable.

@ficcdaf
Copy link

ficcdaf commented Dec 3, 2024

Better Obsidian.nvim Integration

If you are like me, you often open Neovim in some other directory like $HOME, and then use obsidian.nvim's Quick Switcher to open your notes. In that case, the previous solutions won't work; the conditional check will fail because the vault path isn't in Neovim's cwd string.

The following solution works for me:

local function resolver(document_path, image_path, fallback)
  local vault_dir = "path/to/your/vault"
  -- Format path for Obsidian vault
  if document_path:find(vault_dir, 1, true) then
    return vault_dir .. "/" .. image_path
  end
  -- fallback to default
  return fallback(document_path, image_path)
end

Simply checking whether the vault path is inside the document_path yields much more consistent results.

@ahmedelgabri
Copy link

@ficcdaf thanks, I tried your fix but it still doesn't work. I don't use Obsidian.nvim, but I will give it a look

@iamKimlong
Copy link

I found the way to make it work for me, you can try it. Here's the snipppet:

config = function()
    require("image").setup({
        backend = "kitty",
        integrations = {
            markdown = {
                enabled = true,
                clear_in_insert_mode = false,
                download_remote_images = true,
                only_render_image_at_cursor = true,
                filetypes = { "markdown", "vimwiki" }, -- markdown extensions (ie. quarto) can go here
                -- Custom function to resolve image paths
                resolve_image_path = function(document_path, image_path, fallback)
                    -- Define the absolute path to your Assets directory
                    local assets_dir = vim.fn.expand("~/path/to/your/images/dir") -- not the path to vault, but to the assets dir

                    -- Check if the image_path is already an absolute path
                    if image_path:match("^/") then
                        -- If it's an absolute path, leave it unchanged
                        return image_path
                    end

                    -- Construct the new image path by prepending the Assets directory
                    local new_image_path = assets_dir .. "/" .. image_path

                    -- Check if the constructed path exists
                    if vim.fn.filereadable(new_image_path) == 1 then
                        return new_image_path
                    else
                        -- If the file doesn't exist in Assets, fallback to default behavior
                        return fallback(document_path, image_path)
                    end
                end,
            },

@marcocofano
Copy link

Sorry cos this is closed, I do it like this.. given that it is about obsidian integration, if you setup obsidian attachments like:

-- Specify how to handle attachments.
attachments = {
    img_folder = "assets/imgs",
    ---@param client obsidian.Client
    ---@param path obsidian.Path the absolute path to the image file
    ---@return string
    img_text_func = function(client, path)
        path = client:vault_relative_path(path) or path
        return string.format("![%s](%s)", path.name, path)
    end,
},

you can use the command ObsidianImgPaste to paste images from clipboard. and it will create a link like setup before in img_text_func.

and you could use this configuration in image:

require("image").setup({
    backend = "kitty",
    kitty_method = "normal",
    integrations = {
        markdown = {
            enabled = true,
            resolve_image_path = function(document_path, image_path, fallback)
                local obsidian_client = require("obsidian").get_client()
                    local new_image_path = obsidian_client:vault_relative_path(image_path).filename
                    if vim.fn.filereadable(new_image_path) == 1 then
                        return new_image_path
                    else
                        return fallback(document_path, image_path)
                    end
            end,

so if you change the assets directory in obsidian it keeps the integration with image. (you can add some checks on the require, in my case obsidian is loaded on markdown files so it just works)

@edmondop
Copy link

@marcocofano I had to change the integration, the vault_relative_path of an asset doesn't return for me the subfolder...

					local full_path = vault_img_folder .. "/" .. image_path
					local new_image_path = obsidian_client:vault_relative_path(full_path).filename
					vim.notify("new image path " .. new_image_path)

@jonathanmorris180
Copy link

For anyone needing to format Obsidian links that have size properties set (if you use the Image Converter plugin these are set):

resolve_image_path = function(document_path, image_path, fallback)
	local working_dir = vim.fn.getcwd()
	-- Format image path for Obsidian notes
	local obsidian_client = require("obsidian").get_client()
	if working_dir:find(obsidian_client:vault_root().filename) then
		if image_path:find("|") then
			image_path = vim.split(image_path, "|")[1]
		end
		local assets_dir = "assets"
		local result =
			string.format("%s/%s/%s", obsidian_client:vault_root().filename, assets_dir, image_path)
		return result
	end
	-- Fallback to the default behavior
	return fallback(document_path, image_path)
end,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants