Editing Joplin .md files directly does not update app contents

I have recently started using command line in Windows 10 (namely Powershell) as a way to quick look for and replace contents across all of my Joplin notes (e.g. replace the string TODO with the string DONE in every note).

When I run this command, I can see that PowerShell successfully edits the contents of the file, and can manually check the edits in the Md files in another program (e.g. Notepad), but the Joplin app itself does not refresh, even if I close out the application completely and re-open it. Why does this happen, and how can I properly edit the Md files from command-line (e.g. Powershell)?

The notes are stored in the sqlite database, not as .md files. Are you editing the files in the sync target? In which case you shouldn't be as you will break the metadata that Joplin requires to maintain the sync. EDIT - jackgruber's answer is better

@MirDavEsc
Do not directly edit the files in the sync target! This can lead to a lot of sync errors and inconsistencies.
Use the data API, which can be used e.g. via powershell, python, ...

3 Likes

This is a very useful answer, @JackGruber . I knew of the data API before but the tutorial is not great for someone who has no experience with the REST API or curl. Seeing an actual working script and being able to run it is much more helpful (for me at least) in terms of getting started.

The thing that I am trying to do sounds like a good plugin functionality that someone (me?) can build in the future (working name: Line_Finder):

  1. User provides a string pattern (e.g. TODO)

  2. Plugin searches all notes for every line that has the tag

  3. Plugin creates a new note with the format (| Note_title | Containing_line |)
    e.g.
    | | |
    | --- | --- |
    | Title | Note |
    | Daily standups | TODO Revert git repo to prior version |
    | Finances | TODO Cancel subscription |
    | Side projects | TODO Figure out how curl works |

  4. Optional: allow for string pattern replacement in original notes after extracting lines (e.g. TODO -> DONE)

1 Like

There is already a plugin for this.
You can the note-overview plugin and search for all todos:

<!-- note-overview-plugin
search: type:todo
fields: status, todo_due, title
sort: todo_completed ASC
-->

or for the word todo

<!-- note-overview-plugin
search: todo
fields: title, excerpt
alias: title AS Title, excerpt AS Note
sort: todo_completed ASC
-->

and many more ...

1 Like

I previously wrote a batch tool for searching external attachment resources and replacing them with joplin internal attachment resources, but it did not implement a more general batch replacement function.

https://joplin-utils.rxliuli.com/joplin-batch-web/#/convertExternalLink

Following up on the response: how does the API work if I want to replace text in a note? For instance, in your PowerShell example, you get the body of a note into a variable $body. I want to then do a command like:

$new_body = $body -replace "to be replaced", "replacement string"

and then write new_body as the contents of the old body (for instance, replace TODO with DONE.

I saw in the Joplin API (joplin/api.md at master · laurent22/joplin · GitHub) that I need to use PUT, but the instructions are unclear as to how to make a working function call. Seems someone has used POST with PowerShell before here, but not PUT.

Any help or clarifications would be appreciated!

Quick and dirty, no error handling, no validation, no checks, ...

Set a new body with powershell

$endpoint = "http://localhost:27583"
$token = "xxxxxxxxxxxx"
$noteId = "xxxxxxxxxx"
$newProperties = '{"body": "' + $new_body + '"}'
Invoke-WebRequest ($endpoint + "/notes/" + $noteId + "?token=" + $token) -Method Put -Body $newProperties
1 Like

Hi Jack, are you sure the last Invoke-WebRequest works? When I run the equivalent of what you show, I get a 500 code server error.

$noteBody = $noteContent.body
$newBody = $noteBody -replace "\*\*TODO\*\*", "**DONE**"
$newProperties = '{"body": "' + $newBody + '"}'
Invoke-WebRequest ($joplin_endpoint + "/notes/" + $id + "?token=" + $joplin_token) -Method Put -Body $newProperties
This produces the error below:
Message: [The remote server returned an error: (500) Internal Server Error. ]

For reference, the below does work, so I am pretty sure my endpoint, token, and other parameters are set correctly:
$webContent = Invoke-WebRequest ($joplin_endpoint + "/notes/" + $id+ "?token=" + $joplin_token + "&fields=id,parent_id,title,body") -Method Get

Yes I'm sure.
I think your json for the request is invalid, maybe it contains quotes ...

Confirming that what you wrote was correct. It wasn't quotes, but seems to be about how PowerShell handles the carriage return when applying ConvertFrom-Json. It seems to get rid of "\n" and replace it with some other carriage return character that breaks the Json encoding.

The solution is after ConvertFrom-Json and doing the manipulation (if it's string manipulation, it can also be done in JSON format directly), back-converting the contents using ConvertTo-Json cmdlet before using it in the PUT command. This works better than manually encoding $newProperties as done above.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.