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

Make plugin compatible with wikilinks and all paths #74

Closed
Comprehensive-Jason opened this issue May 24, 2023 · 23 comments
Closed

Make plugin compatible with wikilinks and all paths #74

Comprehensive-Jason opened this issue May 24, 2023 · 23 comments

Comments

@Comprehensive-Jason
Copy link

Currently, the plugin is not compatible with wikilinks and only works on embeds with relative file paths.
The Obsidian Link Converter plugin can convert all the wikilinks in a file into Markdown, and all paths to relative file paths.
The Converter plugin's code could be integrated into this plugin to increase Obsidian compatibility. Wikilinks and paths could be automatically converted into markdown and relative paths.

If needed, I can help with this project. Could have a couple of pointers on where best to add the necessary code in this repo?

@Comprehensive-Jason Comprehensive-Jason changed the title Make plugin compatible with wikilinks Make plugin compatible with wikilinks and all paths May 24, 2023
@mokeyish
Copy link
Owner

mokeyish commented May 24, 2023

Thanks. There are two ways to support wikilinks.

  • Convert the markdown with TypeScript(like Obsidian Link Converter plugin). and fill stdin of pandoc.

  • Write a lua-filter named wiki-links.lua to do convertion, and put it into luaDir.

    Then update the export template command (add --lua-filter="${luaDir}/wiki-links.lua" before other lua-filter)

    '-f markdown --resource-path="${currentDir}" --resource-path="${attachmentFolderPath}" --lua-filter="${luaDir}/markdown.lua" -s -o "${outputPath}" -t commonmark_x-attributes',

    to

    - -f markdown --resource-path="${currentDir}" --resource-path="${attachmentFolderPath}" --lua-filter="${luaDir}/markdown.lua" -s -o "${outputPath}" -t commonmark_x-attributes
    + -f markdown --resource-path="${currentDir}" --resource-path="${attachmentFolderPath}" --lua-filter="${luaDir}/wiki-links.lua"  --lua-filter="${luaDir}/markdown.lua" -s -o "${outputPath}" -t commonmark_x-attributes

    Visit https://pandoc.org/try/
    图片

What do your think?

@Comprehensive-Jason
Copy link
Author

Comprehensive-Jason commented May 25, 2023

I see. I'm way more familiar with the Typescript approach, as I help code another plugin.

I might hold off on working on it for now, as exporting to standard markdown is on the Obsidian roadmap. Once that comes out, it will probably be the best solution.


In the meantime, if anyone else is looking for ways to convert their notes for export, they can use the Link Converter plugin mentioned above to prepare their files for export. I personally use the Obsidian Commander plugin to create the following macro for exporting:
200

I duplicate the note to be exported (so my export preparation doesn't affect the actual note), then use Link Converter to turn all links into standard markdown, then run Linter to standardize my note to match standard Markdown specs and avoid formatting issues with Pandoc, then export.
I hope this is helpful!

@FeralFlora
Copy link
Contributor

@Comprehensive-Jason That's comprehensive alright! Thanks for the Commander macro suggestion!

@Comprehensive-Jason
Copy link
Author

I talked with the Obsidian devs about whether exporting to standard markdown is still a planned feature. They told me the feature will come later and to go ahead with the workaround. I will start work on adding the conversion code.

@vanem
Copy link

vanem commented Jul 30, 2023

In any case, this plugin uses Pandoc, and it is not limited to conversion to Markdown, so it will be relevant even if the Obsidian devs implement .md export

@Comprehensive-Jason
Copy link
Author

Comprehensive-Jason commented Jul 30, 2023

@vanem I'm not trying to convert just to standard Markdown, I'm trying to preprocess Obsidian notes into standard Markdown so that this plugin works correctly.

The chief issue with this plugin right now is that it (and Pandoc) requires standard Markdown links with relative file paths in order to convert properly, while most users of Obsidian use wikilinks with just the file name.

Extra code is needed to convert Obsidian wikilinks into standard Markdown so that the plugin works for everyday users.

@FeralFlora
Copy link
Contributor

FeralFlora commented Sep 1, 2023

This plugin has been compatible with wikilinks for a while using Pandoc extensions, and yesterday, it also became compatible with wikilink images with the latest release of Pandoc! 🎉

The specific attribute that you need, to enable wikilink support, is:

wikilinks_title_after_pipe

To use it, change the default export command (for example to PDF) to:

-f markdown+wikilinks_title_after_pipe --resource-path="${currentPath}" --resource-path="${attachmentFolderPath}" --metadata title="${currentFileName}" -s -o "${outputPath}" -t pdf

You can also add other extensions like mark and lists_without_preceding_blankline that improve Obsidian and Pandoc compatibility, so it becomes:

-f markdown+wikilinks_title_after_pipe+mark+lists_without_preceding_blankline --resource-path="${currentPath}" --resource-path="${attachmentFolderPath}" --metadata title="${currentFileName}" -s -o "${outputPath}" -t pdf

Also note that I removed some bloat in the command, as mentioned in #115.

@Comprehensive-Jason
Copy link
Author

This is pretty cool! I presume we still have to convert to relative file paths though?

@FeralFlora
Copy link
Contributor

FeralFlora commented Sep 3, 2023

I presume we still have to convert to relative file paths though?

Nope, not as long as you supply the resource-path, as in my example above (which is included by default, I think), then it should work with only the filename. Upgrade to Pandoc 3.1.7 and give it a try!

However, note that image sizing is not working yet, since you can't use link attributes with wikilinks. I've raised this issue on the Pandoc repo here, but the devs are reluctant to support the combination of Wikilinks + link attributes, since the apps that use wikilinks don't support the link attributes syntax. You're welcome to join the conversation over on the Pandoc repo!

On the Obsidian side, there's discussion in Forum about supporting link attributes or expanding the existing image sizing syntax to support units here.

@Comprehensive-Jason
Copy link
Author

Comprehensive-Jason commented Sep 3, 2023

@FeralFlora Gotcha. Currently I'm testing with the following:

Arguments: -f markdown+wikilinks_title_after_pipe+mark+lists_without_preceding_blankline --resource-path="${currentDir}" --resource-path="${attachmentFolderPath}" --lua-filter="${luaDir}/pdf.lua" ${ options.textemplate ? `--resource-path="${pluginDir}/textemplate" --template="${options.textemplate}"` : ` ` } --embed-resources --standalone -s -o "${outputPath}" -t pdf
Extra arguments: --pdf-engine=pdflatex

Internal links and embedding works fine with the following folder structures:

Vault
└── Attachments Folder (set in Obsidian)
    └── imageToEmbed.png
    └── note.md

OR

Vault
└── note.md
└── Attachments Folder (set in Obsidian)
    └── imageToEmbed

When ![[imageToEmbed.png]] is written in note.md, and note.md is placed inside the Attachments folder alongside the image such that they share the exact same directory, the embedding works properly.
Embedding also works properly if note.md is kept outside of any folders while inside the vault.


However, when I use a more normal folder structure, where note.md is in its own folder separate from the image:

Vault
└── Attachments Folder (set in Obsidian)
    └── imageToEmbed.png
└── Notes Folder
    └──note.md

I get the following error:
image

I think the issue is with how the plugin is replacing ${attachmentFolderPath}.
The plugin replaces "${currentDir}" with "C:\Users\jason\AppData\Roaming\obsidian\Obsidian Sandbox\Notes".
However, it only replaces "${attachmentFolderPath}" with "Attachments", omitting the rest of the path.

When I explicitly insert the full path "C:\Users\jason\AppData\Roaming\obsidian\Obsidian Sandbox\Attachments" instead of using ${attachmentFolderPath}, everything exports perfectly.

All in all, I think this is quite a minor fix for the plugin. First, we replace ${attachmentFolderPath} with ${vaultDir}/${attachmentFolderPath} in all the templates. Then, we could add a toggle in the plugin settings that appends +wikilinks_title_after_pipe so the user can quickly enable wikilink compatibility.

@mrlinuxfish
Copy link

-f markdown+wikilinks_title_after_pipe --resource-path="${currentPath}" --resource-path="${attachmentFolderPath}" --metadata title="${currentFileName}" -s -o "${outputPath}" -t pdf

For some reason, using these settings I can't export contents of an expanded link such as ![[note]] because it thinks the links to notes are images. Using the default pdf export command had these links showing as plain text which is also not what I was aiming for.

@Comprehensive-Jason
Copy link
Author

@mrlinuxfish This is a different issue tracked in #14 .

@FeralFlora
Copy link
Contributor

However, when I use a more normal folder structure, where note.md is in its own folder separate from the image:

For me, I can export with the command I shared, even though my files are located as follows:

Vault
└── Inbox
    └──note.md
 └── Attachments Folder (set in Obsidian)
    └── imageToEmbed.png

I just realized that this is because I have the full resource path in my defaults file. This is what enhancing export prints in the console:
pandoc -f markdown+wikilinks_title_after_pipe+mark+lists_without_preceding_blankline --resource-path="C:\Users\User\Documents\Notes\Obsidian-notes\01 - Inbox\Cat test.md" --resource-path="06 - Resources" --metadata title="Cat test" -s -o "C:\Users\User\Documents\Notes\Obsidian-notes\09 - Outputs/Cat test.pdf" -t pdf --defaults=C:\Users\user\Documents\Notes\Obsidian-notes\pandoc.yaml --citeproc "C:\Users\User\Documents\Notes\Obsidian-notes\01 - Inbox\Cat test.md"

So I guess it would fail for me without the defaults file too, and you are right that ${vaultDir} is needed in the template. Perhaps a better solution would be for ${attachmentFolderPath}} to actually resolve as the full path to the attachments folder.

Then, we could add a toggle in the plugin settings that appends +wikilinks_title_after_pipe so the user can quickly enable wikilink compatibility.

I agree, such a toggle would be nice.

@Comprehensive-Jason
Copy link
Author

@FeralFlora Sounds like a plan! I'll get working on a PR for it then.

@TimFruit
Copy link

TimFruit commented Nov 4, 2023

Thanks. There are two ways to support wikilinks.

* Convert the markdown with TypeScript(like [Obsidian Link Converter plugin](https://github.com/ozntel/obsidian-link-converter)). and fill stdin of pandoc.

* Write a [lua-filter](https://pandoc.org/lua-filters.html) named `wiki-links.lua` to do convertion, and put it into [luaDir](https://github.com/mokeyish/obsidian-enhancing-export/tree/main/lua).
  Then update the export template command (add `--lua-filter="${luaDir}/wiki-links.lua"` before other lua-filter)
  https://github.com/mokeyish/obsidian-enhancing-export/blob/04176511ba5f07bfa1073919bee0c12a9ceb4855/src/export_command_templates.ts#L25
  
  to
  ```diff
  - -f markdown --resource-path="${currentDir}" --resource-path="${attachmentFolderPath}" --lua-filter="${luaDir}/markdown.lua" -s -o "${outputPath}" -t commonmark_x-attributes
  + -f markdown --resource-path="${currentDir}" --resource-path="${attachmentFolderPath}" --lua-filter="${luaDir}/wiki-links.lua"  --lua-filter="${luaDir}/markdown.lua" -s -o "${outputPath}" -t commonmark_x-attributes
  ```
  
  
      
        
      
  
        
      
  
      
    
  Visit https://pandoc.org/try/
  <img alt="图片" width="1403" src="https://user-images.githubusercontent.com/16131917/240490128-5637d4f3-4e01-4017-a37c-a5ce03f21a79.png">

What do your think?

Thanks, i use the second way,it works

here is the lua code:

function Pandoc(doc)
  -- 遍历文档中的所有块元素
  for i, block in pairs(doc.blocks) do
    if block.t == 'Para' then
      -- 在段落文本中进行替换
      doc.blocks[i] = pandoc.Para(replace_wikilinks(block.content))
    end
  end
  return doc
end

function replace_wikilinks(content)
  local new_content = {}
  local text = pandoc.utils.stringify(content)

  -- 使用正则表达式匹配文本中的 Wikilink 格式
  text = text:gsub("!(%[%[[^%]]*%]%])", function(link)
    local img_path = link:match("%[%[([^%]]*)%]%]")
    return "![](" .. img_path .. ")"
  end)

  return pandoc.read(text).blocks[1].content
end

return { { Pandoc = Pandoc } }

@mokeyish
Copy link
Owner

mokeyish commented Nov 4, 2023

@TimFruit Looks great, Are you willing to submit a PR?

@TimFruit
Copy link

TimFruit commented Nov 4, 2023

@TimFruit Looks great, Are you willing to submit a PR?

sorry,i don't want to submit a PR. Writing pandoc lua scripts is difficult for me, I asked chat gpt to get this code

@FeralFlora
Copy link
Contributor

@TimFruit Looks great, Are you willing to submit a PR?

For standard markdown, wouldn't it be easier to just add the wikilinks_title_after_pipe extension (Pandoc docs here) rather than using a lua filter to convert the wikilinks to markdown links?

As is, gfm and commonmark don't support the use wikilinks_title_after_pipe extension for image links yet, but it looks like support will be added for that soon. Progress on that is tracked here: jgm/pandoc#9164

Until then, the lua filter might be relevant for gfm and commonmark, but I think the most straightforward option for markdown is to just use the extension.

@Comprehensive-Jason mentioned making a PR to change the default command, not sure if there's any progress on that? This requires ${attachmentFolderPath}} to actually resolve as the full path to the attachments folder. Alternatively, the commands could be changed from ${attachmentFolderPath} to ${vaultDir}/${attachmentFolderPath}.

@universvm
Copy link
Contributor

@Comprehensive-Jason I was wondering whether you need help with the PR?

@daeh
Copy link

daeh commented Jan 24, 2024

Just voicing my enthusiastic support for this

@mokeyish
Copy link
Owner

mokeyish commented Feb 2, 2024

#154

@mokeyish mokeyish closed this as completed Feb 2, 2024
@jeetsukumaran
Copy link

jeetsukumaran commented Feb 23, 2024

Folks, I've been working on a similar problem, to get Obsidian style "|100" to set the width for images in pandoc beamer output.

Thought I would share some code here in case it helps with this problem.

The following works for wikilink images to propagate any given width/height attributes to resize the image:

function Image(elem)
    local captionStr = pandoc.utils.stringify(elem.caption)
    local parts = {}
    for part in string.gmatch(captionStr, "[^|]+") do
        table.insert(parts, string.match(part, "^%s*(.-)%s*$")) -- Trim whitespace
    end
    local width, height = nil, nil
    if #parts > 0 then
        width, height = parts[#parts]:match("^(%d+)%s*x?%s*(%d*)$")
        if width then
            table.remove(parts, #parts)
        end
    end
    if width then
        elem.attributes.width = width
        if height and height ~= "" then
            elem.attributes.height = height
        end
    end
    if #parts > 0 then
        local newCaption = table.concat(parts, " | ")
        elem.caption = pandoc.read(newCaption, 'markdown').blocks[1].content
    else
        elem.caption = {}
    end
    return elem
end

e.g.

![[attachments/files/Pasted image 20240222051816.png| 100]]

![[attachments/files/Pasted image 20240222051816.png| Real caption. | 100]]

P.s.

The approach is not perfect for my use case because I would like to remove the width attribute from the display figure caption. Problem is that even thought the element caption is updated, the figure remains showing the old caption.

As a MWE to illustrate the problem, try this filter:

function Image(elem)
    elem.caption = pandoc.List({pandoc.Str("foo")});
    return elem
end

return {
    {
        Image = Image,
    }
}

when applied to a document with:

![[attachments/files/Pasted image 20240222051816.png| real caption | 100]]

we get:

image

(image hidden; only caption shown)

So the image caption is updated, but the figure text is not.


It seems like pandoc generates the figure text before the lua filter sees element. The following for example updates no "Figure" captions, though the element is updated.

function Image(elem)
    elem.caption = pandoc.List({pandoc.Str("foo")});
    return elem
end

return {
    {
        Image = Image,
    }
}

@FeralFlora
Copy link
Contributor

Perhaps a better solution would be for ${attachmentFolderPath}} to actually resolve as the full path to the attachments folder.

@Comprehensive-Jason @universvm I just submitted a PR which introduces this change: #174

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

9 participants