it is unreasonable to expect the user of a plugin to fork it and modify it just to avoid data loss from a core function of Obsidian
More generally, it’s unreasonable to expect the user of Obsidian to prevent Obsidian from causing data loss in the first place. Even when not shifting blame to the plugin developer, it’s bad that Obsidian destructively modifies YAML frontmatter.
the automtatic removal of comments is incredibly annoying and poorly chosen. using dataveiew to filter based on frontmatter fields is incredibly powerful. It allows the easy creation and handling of specialized notes of many different types while consistently handling notes of a given type. The downside of this is that frontmatter can get fairly complex. comments allow one to quickly review frontmatter and make sure the right fields are on a given note and create consistency across notes. further, for those using LLMs to interacting with obsidian, comments allow the LLM to more efficiently understand a note type and work across note types.
automatically removing comments creates unexpected behavior for the user, makes vault management more difficult, and is problematic for more sophisticated use cases. there has to be a way to solve the API issue without automatically deleting user content and kneecapping obsidian’s potential
Obsidian has decided that deleting all comments in the yaml is a sound decision, and I would like to request that it be reversed.
Why it’s bad form to delete comments
As programmers you ought to know that comments can be essential to code: they act as definitions, explanations, reminders, and are often essential when handing over the code to a different user. They are not “arbitrary comments” as you mention in your reply to my bug report.
Comments are data, and data should NEVER be deleted period, let alone without warning or permission.
When does this deletion occur?
Obsidian has chosen to automatically re-format yaml to the long form whenever you modify (or accidentally modify) the yaml in reading mode or live preview mode. Apparently this was done to make it easier for those who create plugins.
Personally I do not think it is right to change my notes even if it is just yaml format. But what is definitely not fine is deleting my yaml comments. If Obsidian has not found a way to reformat yaml without deleting user comments, then it should not be reformatting the yaml. And if deleting the comments is a separate process from reformatting the yaml, then it should be easy enough to stop deleting the comments.
That’s worse, isn’t it? I mean I found out by accident yesterday. So how many of my comments have been deleted without my knowing? And how many Obsidian users still don’t know about this?
Using bases in a custom code block, as opposed to a bases file, entering code mostly by hand, I’m finding comments and blank lines in the yaml useful, but if I make changes to the code interactively using the menus my comments are trashed.
Proposed solution
retain comments and blank lines in the code when making changes interactively
Every single bug report on the topic has been closed by WhiteNoise and redirected to either this post or a much longer post (here)
I don’t know what prevents them from fixing this given the reformating code is basically theirs and you can see in the code at one point you have both the original format and the formatted code. You could easily have a second function handle the application of this formatted code selectively to actual properties and leave the unformatted code alone (comments). You could also ignore properties that have complicated yaml formats and just leave it unformatted. But they don’t.
About this thread, I usually link to licat’s answer to explain that this is not a bug but an intentional design decision to simplify the programmatic handling of YAML for ourselves (properties, bases) and for plugins (via the API we offer).
Here you all go - I’ve made a quick plugin which will let people keep their comments:
The way this plugin works is by hooking into Obsidian’s built-in processFrontMatter() function, so this will be compatible with any other plugin. I don’t make any changes to the original function, I just inject the original comments again after it runs.
It’s not in the plugin store so you’ll need to install it from BRAT:
Install the BRAT plugin from the Community Plugins.
Open the Settings page for BRAT.
Click “Add Beta Plugin”.
Paste in this address: https://github.com/alangrainger/obsidian-yaml-comments
Click “Add Plugin”.
As I’m modifying a built-in function, I don’t believe it will be accepted in the store, but if you want to submit it yourself, you are more than welcome.
NOTE: This works for full comment lines, but not inline comments. It could be done, but the regex was pointlessly tricky with hash symbols in quoted strings, so I’ll leave that for someone else to pick up and submit a PR.
e.g.:
---
some_prop: Some value
# This comment will be kept ✅
foo: bar
some_list:
- item 1 # this comment won't be kept ❌
# But this comment will be kept ✅
- item 2
tada: Hooray!
---
I don’t use comments myself, but hopefully this helps someone.
How did you test that it works? The override function as implemented in the BRAT plugin doesn’t ever run on my end, it just loads and unloads but nothing uses the override. I assume the updateProperty() call has the prototype version of processFrontMatter built in?
Ctrl+Shift+I, Sources, app.js shows updateProperty() being one of two places that call processFrontMatter; I haven’t figured out how to get any override to run though. Replacing the _proto_ does show the function gets replaced, replacing the function itself does the same. But it never gets run. If you call either, it runs the right function. I assume this.ctx.app might be a different instance of app and have a fileManager that’s run before the _proto_ or original function get replaced? I assume the whole thing is a case of earlier instances not inheriting the changes you make to the class later.
e.prototype.updateProperty = function(e, t) {
return y(this, void 0, Promise, (function() {
var n;
return b(this, (function(i) {
switch (i.label) {
case 0:
return n = KO(this.frontmatter, e),
[4, this.ctx.app.fileManager.processFrontMatter(this.file, (function(e) {
if (("" === t || Array.isArray(t) && 0 === t.length) && (t = null),
!e.hasOwnProperty(n) && null == t)
return e;
e[n] = t
}
))];
case 1:
return i.sent(),
[2]
}
}
))
}
))
}
No idea if this is a better place to replace functions, but I’ve dug very deep into the inspector to find out where properties are formatted, and I’m confident processFrontMatter is too high up the chain (actually, it never gets called outside of API calls); if you Ctrl+F class Qv { you’ll find the class and functions handling formatting. The code in there includes what I assume is the YAML library. Ctrl+F function Ex(e, t) { (the variant with var n = Cx(t), i = hC(e).contentStart;), breakpoint it before changing a property in the properties display - you will see that e contains your unformatted code (containing comments), and n=Cx(t) contains the formatted code (without comments). I don’t know how you would replace that, but if you could, that might be better still.
@Alistaire what are you/Obsidian doing that calls updateProperty()? I haven’t experienced this (in my admittedly limited testing, since I don’t personally use comments) so I need to know how to make that happen so I debug it.
Step-by-step guide to capture the YAML being edited:
Open Obsidian
Ctrl+Shift+I
Go to Sources
Open top/obsidian.md/app.js
Click the { } icon (next to Line _ Column _) in the bottom-left of the source view to Pretty print the code
Search function Ex(e, t) { with next line var n = Cx(t) and , i = hC(e).contentStart;
Click the - icon on the left of the line to add a breakpoint ====> on the var n = Cx(t) line
Close with Ctrl+Shift+I
Create a new note
Switch to source mode
Paste YAML that will convert such as the YAML in the manual
Switch back to live preview mode
Click Add property and type some property name
Your event is now caught in the Ex(e,t) breakpoint and you can see e is the original YAML, t is the array object
F10 or Ctrl+' to step over the current line to populate n, which is the formatted YAML
You can see the rest of the call stack in section Call Stack in the part that says Debugger paused in yellow and has the Breakpoints. Depending on what you edit in the property view, you will capture e.handleUpdateKey, e.handleUpdateValue.
F8 or Ctrl+\ continues running the code
Ctrl+Shift+I closes debugger
Show source mode of the note, you see the YAML has been overridden
Regardless of what you do in the properties or bases view, the YAML gets overridden going through the Ex(e,t) function
It also seems that e.prototype.updateProperty also isn’t capturable for whatever reason; perhaps it also doesn’t get called. I brought it up because it’s something calling processFrontMatter, but it itself also seems not to be called.