obsidian-dataview icon indicating copy to clipboard operation
obsidian-dataview copied to clipboard

Is there a way to reuse js code in dataviewjs?

Open duoani opened this issue 3 years ago • 11 comments

I have some dataviewjs code blocks defined in some .md files, and they are very similar. Such as some utils functions. I wonder is there a way to place this code together, and import it to a dataviewjs block, just like import statement in ES6?

duoani avatar Jun 07 '21 08:06 duoani

I'd find the way. I got the path of the vault root form dv.app.vault.adapter.basePath, and then require() the scripts.

duoani avatar Jun 07 '21 10:06 duoani

This seems to work, but not on iOS. Here the example I used:

I create a js file <vault>/Queries/library.js with this content:

exports.formatDate = date=> date.toLocaleString({ weekday:'short', day: 'numeric'})

And then you can use it inside a Note

// ```dataviewjs
const lib = require(dv.app.vault.adapter.basePath+'/Queries/library.js')
dv.paragraph(1,lib.formatDate(dv.current().file.ctime))
// ```

If you want to reload the referenced library every time, without restarting obsidian, use this code:

const src = dv.app.vault.adapter.basePath+'/Queries/library.js'
delete global.require.cache[global.require.resolve(src)]
const lib = require(src)

andi0b avatar Jul 21 '21 10:07 andi0b

@andi0b were you able to find a workaround to get this working on iOS?

saml-dev avatar Aug 11 '21 21:08 saml-dev

@andi0b were you able to find a workaround to get this working on iOS?

No, I copy&pasted the code now into every file. Seems to be the better compromise.

andi0b avatar Aug 12 '21 09:08 andi0b

I can add a dv.require() which just eval's code for you (the downside to this being it won't recognize JS modules/require statements properly), which should work across platforms. The main problem is that this all uses asynchronous calls, so you would have to do it as

let code = await dv.require("stuff");

blacksmithgu avatar Aug 13 '21 19:08 blacksmithgu

Hey, I actually created a new plugin — now in the community store — that specifically addresses code reuse. It can be used in dataviewjs blocks as well as templater templates. Check it out and let me know if it helps! https://github.com/samlewis0602/obsidian-custom-js

saml-dev avatar Sep 03 '21 18:09 saml-dev

I can add a dv.require() which just eval's code for you (the downside to this being it won't recognize JS modules/require statements properly), which should work across platforms. The main problem is that this all uses asynchronous calls, so you would have to do it as

let code = await dv.require("stuff");

This would be actually perfect. Nothing against @SamLewis0602 solution here which works good for me currently, but i'd love to have this centralized in here(as the project allows for coding anyways it makes at least sense to me to have said feature available)

Darksider3 avatar Nov 17 '21 18:11 Darksider3

For now, to get this feature "out", I'll probably implement a janky solution which simply loads + evals files for you (with a cache to support recursive includes); the best long-term approach would be to override require() to support loading from the vault on top of it's default behavior, which I think I can do with some proxying.

blacksmithgu avatar Nov 18 '21 20:11 blacksmithgu

I'd be curious to see your solution if you're able to get require() working somehow as that would greatly simplify the API for CustomJS compared to strict format rules due to using eval

saml-dev avatar Nov 23 '21 16:11 saml-dev

What is the status of this issue? I'm interested in the .require() solution as well.

BluBloos avatar Sep 10 '22 12:09 BluBloos

I would recommend going with CustomJS for now. I've seen folks build out user script libraries with it.

AB1908 avatar Sep 10 '22 14:09 AB1908

CustomJS seems to have taken off! We have dv.view() to reuse view code but best replicate business logic via CustomJS especially if you want to use it in other plugins. Closing as not planned.

AB1908 avatar Oct 29 '22 21:10 AB1908