export default class MyPlugin extends Plugin {
async onload() {
var jsonContent = JSON.stringify(this.app.plugins.plugins.breadcrumbs.mainG.toJSON());
console.log(jsonContent)
app.vault.create(".", jsonContent);
and it says
Uncaught (in promise) Error: File already exists.
I also try to search for my variable, but there is no app.plugins.plugins.dotmaker.jsonContent
in the console.
Only the desktop version of Obsidian uses electron, the mobile version uses capacitor.
this.app.vault.create("output.json", jsonContent);
would be the correct function call
you can omit the options
as shown by the ?
, they contain stuff that is not necessary here.
https://marcus.se.net/obsidian-plugin-docs/api/interfaces/DataWriteOptions
I see. It still doesn’t export the file (have check in both the plugin folder and Obsidian folder (C:\Users\ganuo\AppData\Local\Obsidian)).
What is the difference between this.app.class
and app.class
? It seems that the two can be used interchangeably?
Do you know where I can access the jsonContent
string in my console?
It should have create the file in your vaults main directory.
this
is used to make sure you are using the correct App instance as you could define another variable with the same name in your code.
https://dmitripavlutin.com/javascript-scope/
your jsonContent
should already show up in the console.
joethei:
this
is used to make sure you are using the correct App instance as you could define another variable with the same name in your code.
I see. So app
is also a class as well. Reading the documentation I don’t see much explanation of it. Can you explain how it works?
joethei:
your jsonContent
should already show up in the console.
Yes the content of that variable is displayed in the console, but I cannot call it again directly in it. Both jsonContent
and this.app.plugins.plugins.dotmaker.jsonContent
do not work.
I want to automatically update the output every time the plugin runs. create
cannot overwrite the file, so I guess modify
is the way to go. But I get:
Uncaught (in promise) TypeError: Cannot create property ‘saving’ on string ‘output.json’
Do you know how to fix?
Ooker:
Anyway, I wonder why it decides that the current location is the main vault, not in the plugin directory, where the js file locates?
Because all operations by the vault class are relative to the vaults main directory.
You can use the following snippet to get the correct directory.
const configPath = this.app.vault.configDir + "/plugins/.../";
The App
class represents the currenlty running instance of obsidian.
Ooker:
Yes the content of that variable is displayed in the console, but I cannot call it again directly in it. Both jsonContent
and this.app.plugins.plugins.dotmaker.jsonContent
do not work.
This is because your jsonContent
variable is only accesible inside your onload()
function, to be able to read it you need to change its scope(see the link in my last reply).
The modify function requires the use of a TFile
, you can get
this by using the getAbstractFileByPath function and the checking if the returned value is instanceof TFile
.
If this is not the case you should create the file.
One thing I do notice is that you do not use TypeScript(which is the default for obsidian) to write your plugin, it should not even allowed you to compile the plugin.
Here is a short tutorial to get you started:
https://phibr0.medium.com/how-to-create-your-own-obsidian-plugin-53f2d5d44046
Thanks. I wasn’t aware about onload()
.
Is this the correct code? It returns null
instead of instanceof TFile
const configPath = this.app.vault.configDir + "/plugins/.../";
this.app.vault.getAbstractFileByPath(configPath)
One thing I do notice is that you do not use TypeScript(which is the default for obsidian) to write your plugin, it should not even allowed you to compile the plugin.
I don’t know. I’m editing the sample plugin, so I’m actually coding with ts right now. npm can still compile it to js
All of these are null:
this.app.vault.getAbstractFileByPath(".")
this.app.vault.getAbstractFileByPath(".obsidian")
this.app.vault.getAbstractFileByPath(this.app.vault.configDir)
this.app.vault.getAbstractFileByPath("D:/")
However, it’s interesting that when I use the path "/"
, I get a circular object:
JSON.stringify(this.app.vault.getAbstractFileByPath("/"))
VM314:1 Uncaught TypeError: Converting circular structure to JSON
--> starting at object with constructor 'e'
| property '_' -> object with constructor 'Object'
| property 'rename' -> object with constructor 'Array'
| index 0 -> object with constructor 'Object'
--- property 'e' closes the circle
at JSON.stringify (<anonymous>)
at <anonymous>:1:6
getAbstractFileByPath
always returned null
if path included a hidden folder (e.g. : .obsidian
). Not sure what I am doing wrong.
So I decided to use app.vault.adapter.exists
instead.
To create and overwrite a file, I just use app.vault.adapter.write
. To read it if it exists, app.vault.adapter.read
.
Not sure if it is the proper way to read/write files inside an Obsidian vault, but it seems to work here (so far I’ve only been able to test on Windows, Android 12 and iPad).
JamesKF:
getAbstractFileByPath
always returned null
if path included a hidden folder (e.g. : .obsidian
)
Hmm, I use getAbstractFileByPath
for a file that is outside the vault and a file inside that vault, and both are not contained in a hidden folder, and it’s still null.
JamesKF:
So I decided to use app.vault.adapter.exists
instead.
To create and overwrite a file, I just use app.vault.adapter.write
. To read it if it exists, app.vault.adapter.read
.
Here is how this works:
const configPath = this.app.vault.configDir + "/plugins/dotmaker/data.json";
app.vault.adapter.exists(configPath)
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: true
app.vault.adapter.read(configPath)
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: ""
app.vault.adapter.write(configPath)
[[PromiseState]]: "rejected"
[[PromiseResult]]: "TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
fileinside = app.vault.adapter.basePath + "\\.obsidian\\plugins\\dotmaker\\data.json";
app.vault.adapter.exists(fileinside)
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: false
app.vault.adapter.read(fileinside)
[[PromiseState]]: "rejected"
[[PromiseResult]]: Error: "ENOENT: no such file or directory, open 'D:\Quả Cầu\B Nội dung\Knowledge graphs\Cây vấn đề\D:\Quả Cầu\B Nội dung\Knowledge graphs\Cây vấn đề\.obsidian\plugins\dotmaker\data.json'"
app.vault.adapter.write(fileinside)
[[PromiseState]]: "rejected"
[[PromiseResult]]: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
For the file with absolute path outside .obsidian but inside vault, the error is the same with the file inside .obsidian.
checking the properties of app.vault.adapter
I see a writeFile()
fsPromise, with the arguments like this:
I try app.vault.adapter.writeFile(configPath, output)
and it doesn’t work, but the autocomplete suggests me to try app.vault.adapter.write(configPath, output)
. This time it works. I have no idea how to get to understand solution though
You would be better off reading the docs for the adapter class,
there is a write
function that takes 3 parameters, the third being optional:
https://marcus.se.net/obsidian-plugin-docs/api/interfaces/DataAdapter#write
The writeFile()
function is not documented and is an internal function, so I would recommend not using that.