twibiral / obsidian-execute-code

Obsidian Plugin to execute code in a note.
MIT License
1.09k stars 66 forks source link

[FR] access to dataviewjs dv variable #83

Open sergeBoisse opened 2 years ago

sergeBoisse commented 2 years ago

Hello, this would be nice if a javascript snippet could have access to the dataviewjs dv variable (provided the dataview plugin is also installed in obsidian). This would allow js code snippets to create on the fly html elements like text, divs or buttons in the doc in preview mode (just below the snippet) and to attach event handlers to them. This might not be too difficult to do, as dataview already provides an API for plugin developpers :https://blacksmithgu.github.io/obsidian-dataview/plugin/develop-against-dataview/

for example, this works in a dataviewjs snippet, but it would be nice if it worked also right in a js snippet by clicking the "run" button

const bouton=dv.el("button","hello");
const inp = dv.el("input","type something");
const sortie = dv.el("p","???");

bouton.addEventListener('click', (e) => 
        { inp.value="hello, edit me!"});
inp.addEventListener('input', (e) => 
        {test(e.target.value)});
function test(val) {
    sortie.innerHTML=val;
}
chlohal commented 2 years ago

Hey! Looking at the dataview plugin's code, it seems they use an eval function to run the code in the same process as Obsidian. We run all code in separate processes so that the plugin can support languages other than Javascript. Because of that, dv might be harder to support for us.

I will look into it and see how complex their API is. It's possible that we could get some kind of stub injection-- Thank you for your feature request!

chlohal commented 2 years ago

I've looked at their API, and unfortunately, it seems like this would be rather difficult to do. We would have to either a. find a way to transfer objects across process borders, or b. pass opaque "pointer objects", which only contain an ID, that we can then reference to DV objects in the Obsidian process. Either way, it's very hard for me to promise full feature parity.

There's a possibility that we could do this at a later point, but I am not sure if it's feasible at this time. If anyone else has any other ideas, please suggest them :)

sergeBoisse commented 2 years ago

Thank you Chohal for your reply. Actually I was thinking about a way for Obsidian-execute-code to dynamically manipulate the note DOM using js, and dataviewJS was a way to do that. But then I have found that it is not necessary ; you can indeed create HTML elements programmatically by using just your amazing plugin! For example :

//console.log(`$\\pi$ = 3.14`); // oK mais mathsjax is not recognized
console.log('<input type="text" id="name" name="name" required   minlength="4" maxlength="20" size="20" oninput="mydiv.innerHTML=this.value;">');
console.log("<div id=mydiv>Type some text above</div>"); // works !

Click the run button and voila, you have an interactive small app !

chlohal commented 2 years ago

That's great! I'm glad that you found a workaround.

I do want to make you aware that we may be changing this behavior in the future to fix issue #89: some languages print things like <class int> or HashMap<String>, and we want to be sure to support that too, instead of treating it like HTML. you might need to change your code, but we will make sure there is a method to create HTML elements programmatically, and that it will be an easy swap-over from the console.log solution. Something that we're considering now is an @html(...) magic function, which will dynamically output whatever HTML you give it. wanted to ensure you were informed! :)

mayurankv commented 1 year ago

I've looked at their API, and unfortunately, it seems like this would be rather difficult to do. We would have to either a. find a way to transfer objects across process borders, or b. pass opaque "pointer objects", which only contain an ID, that we can then reference to DV objects in the Obsidian process. Either way, it's very hard for me to promise full feature parity.

There's a possibility that we could do this at a later point, but I am not sure if it's feasible at this time. If anyone else has any other ideas, please suggest them :)

I've looked at their API, and unfortunately, it seems like this would be rather difficult to do. We would have to either a. find a way to transfer objects across process borders, or b. pass opaque "pointer objects", which only contain an ID, that we can then reference to DV objects in the Obsidian process. Either way, it's very hard for me to promise full feature parity.

There's a possibility that we could do this at a later point, but I am not sure if it's feasible at this time. If anyone else has any other ideas, please suggest them :)

Just wondering, is this still true if you don't want to change dataview variables. Rather, akin to magic commands, just pull some metadata in as an input, evaluate that before running, and then go? This combined with programatically created html would definitely do the trick for me at least. Please let me know if that is or isn't really feasible.

chlohal commented 1 year ago

Sure, that's feasible! What metadata would you want access to?

mayurankv commented 1 year ago

Ideally any dataview or frontmatter defined field right? Barring that, specifying in the plugin settings which metadata fields you want to be parsed would work too.

mayurankv commented 1 year ago

Hi! Was just wondering whether this was still something you guys were considering? I've realised that dataview inline fields wouldn't be the best to deal with right now (at least until dataview releases its parser for access in other plugins), but frontmatter metadata I believe should be pretty easy to extract and pull in as magic commands.

twibiral commented 1 year ago

@mayurankv Yes, but it doesn't have a very high priority

grepler commented 1 year ago

following up on this, it would be amazing to be able to pull in values from inline dataview lookups (for example an IP address and inject it into a shell command, etc.).

An expansion of the magic commands would be terrific.