uniorg
uniorg copied to clipboard
Which backend does uniorg use?
I'm trying to get Org-Roam UI to recognise a link setup.
:follow just works as expected, :export to 'html works as well. In Roam UI, nothing show up rendered. Since they're using uniorg it seemed prudent to ask here directly what I can do so uniorg recognises added link types.
Hi. Uniorg is an org-mode parser/org-to-html converter implemented in typescript. Therefore, it doesn't use any org backend (or any elisp code) but tries to follow html.
I'm not sure I fully understand what you're trying to achieve. Could you share your example org file and desired html output?
Hi,
The org link is
[[obsidian:Vaultname:Example_file]]
It ends up dangling around in a span tag as obsidian:Vaultname:Example_file
The link the 'html exports comes out as
obsidian://open?vault=Vaultname&file=Examplefile
this is the link type setup:
(org-link-set-parameters
"obsidian"
:follow
(lambda (path)
(cl-destructuring-bind
(vault file) (split-string path ":")
(browse-url (format "obsidian://open?vault=%s&file=%s" vault file))
)
)
:export
(lambda (path description backend info)
(cl-destructuring-bind
(vault file) (split-string path ":")
(format (pcase backend
('html "<a href=\"obsidian://open?vault=%s&file=%s\">%s</a>"))
vault file description)))
)
When you say "it tries to follow html", does that mean I can add to html and it follows what's in that or that it's set up to follow org's basic html "factory settings"?
"It tries to follow html" means that when implementing features I try to re-implement html backend behavior as close as makes sense. It mostly follows defaults but there are some configuration variables it re-implements as well (again, trying to follow elisp implementation if it makes sense).
The behavior you want to achieve can be implemented with a small unified plugin (you would need to modify org-roam-ui):
const processor = unified()
...
.use(uniorgRehype)
// the plugin must be applied after uniorg-rehype
.use(inspectUrls, { // inspectUrls from rehype-url-inspector
inspectEach: ({ url, node, propertyName }) => {
if (url.startsWith('obsidian:')) {
const [obsidian, vault, file] = url.split(':');
node[propertyName] = `obsidian://open?vault=${vault}&file=${file}`;
}
},
});
It might be possible to implement this in a more generic way but you would still need to hack org-roam-ui to add your conversion function (as uniorg cannot call into elisp functions)
Thank you. I'll give that a shot and see what happens.
OK I've tried to find where something like that could be put. And the Sidebar/Link.tsx could be a candidate. No Idea how to implement it though, there's nothing resembling your example.
This is the place: util/processOrg.tsx
Thanks again for your help.
I've now modified it to this
const orgProcessor = unified()
.use(uniorgParse)
.use(extractKeywords)
.use(attachments, {
idDir: attachDir || undefined,
useInheritance,
})
.use(uniorgSlug)
.use(uniorg2rehype, { useSections: true })
.use(inspectUrls, {
inspectEach: ({ url, node, propertyName }) => {
if (url.startsWith('obsidian:')) {
const [obsidian, vault, file] = url.split(':');
node[propertyName] = `obsidian://open?vault=${vault}&file=${file}`;
}
},
})
And it made no difference. Instead of links, it still renders as <span class"chakra-text obsidian:vaultname:filename css-1wobba0">Description</span>
This wont really work, org-roam-ui is not setup to handle foreign non-http links.
Here is where http(s) links are handled, all other links get converted to spans. https://github.com/org-roam/org-roam-ui/blob/5ac74960231db0bf7783c2ba7a19a60f582e91ab/components/Sidebar/Link.tsx#L187-L189
If you want to manually add support for this, you can change it to something like
if (type.replaceAll(/(http)?.*/g, '$1') || /^obsidian/.test(type)) {
return <NormalLink href={href}>{children}</NormalLink>
}
@tefkah oh, is there any reason why they are converted to spans?
Hmmm I think it was to filter out bad links, e.g. to nonexisting nodes. Didn't think people would be using non-http/non-org-roam links in org-roam!