obsidian-dataview
obsidian-dataview copied to clipboard
Nested Inline Fields
Is your feature request related to a problem? Please describe. Frontmatter data can be arbitrarily nested however as far as I understand it your inline field system is limited to just top level keys and values.
Describe the solution you'd like It would be nice if there was a way to describe arbitrarily nested data through the inline fields as well. This may be incompatible with the current implementation so I understand if you mark this as won't-fix
For example I would like to collect all date ranges under the date
key for easy accessing.
In YAML I would do something like this.
---
date:
construction: 2000
life: 2000-2020
demolition: 2020
---
Could be defined inline as
(date:: construction:: 2000)
(date:: life:: 2000-2020)
(date:: demolition:: 2020)
And rendered like this
Additional Context There are some compatibility issues that I don't have answers to eg what would the following look like in data form
(date:: 2000)
(date:: life:: 2000-2020)
or this
(date:: 2000)
(date:: 2020)
(date:: life:: 2000-2020)
As usual, can get around this with a bit of DVJS but this would need a parser enhancement. On Discord, ScholarInTraining did some testing around nested fields:
https://discord.com/channels/686053708261228577/875721010144477204/998989466377138239
Thanks! Ok on a short example I can make both ReadingLog and rating appear if I wrap them in different inline syntax formats. I'm not sure why ReadingLog needs to be wrapped.
[ReadingLog:: here is some text (rating:: 9/10) and here is some more text] (test query was TABLE without id ReadingLog, rating FROM "pathToMyTestFile"). If I use parens on ReadingLog also, then rating does not show up. I assume I could swap the parens and brackets.
As a more philosophical question, why use the inline keys over YAML frontmatter? YAML probably is the most terse way to describe nested objects.
@blacksmithgu said:
As a more philosophical question, why use the inline keys over YAML frontmatter? YAML probably is the most terse way to describe nested objects.
Some folks like to hide their frontmatter in reading view, or want the data inline in the note under a heading or to add additional commentary.
YAML is also tricky about certain characters, which can be user-unfriendly.
The Obsidian Forums see lots of questions about correlated inline fields each being annotated multiple times in the same file, and the user wants each entry to be a different row. Since there are multiple correlated fields, I do not think FLATTEN
alone can solve the problem, while nesting the fields in an object, making an object with all the fields for each update, and then flattening the outer object in the query should do the trick. An example use case might be expense reporting, or I just saw one about meal tracking. I personally would feel awkward writing that much text in my YAML, even if I had a better understanding of which characters needed to be escaped.
At that point, it's probably much better to write your own parser haha. See #967.
I have solved this particular issue in a different way outside of the dataview plugin. I thought I would just thought I would open the discussion.
Had some more thoughts on this and decided that the alternative I had found has some issues.
I like this method
[ReadingLog:: here is some text (rating:: 9/10) and here is some more text]
It seems to render odd though. Dataview 0.5.41
(date:: [construction:: 1886-1894])
(date:: [life:: 1894-])
It seems to display correctly if you are using the same types of bracket.
[test:: [test:: [test:: 2020]]]
(test:: (test:: (test:: 2020)))
I think it is an issue with the order that they are resolved. It seems to handle each type of bracket individually which means that it is possible to get matches that intersect. It seems the simplest solution is just to check if a matched group intersects any of the previous matches and if it does discard it. https://github.com/blacksmithgu/obsidian-dataview/blob/master/src/data-import/inline-field.ts#L141
I have opened a pull request to fix the html corruption.
I have had some more thoughts on how the data should be structured when parsed.
Examples
Here are some examples of how the plugin currently parses data (I believe)
Example 1
[key:: value]
becomes
{"key": "value"}
Example 2
[key1:: value1]
[key1:: value2]
becomes
{"key1": ["value1", "value2"]}
Example 3
[key1:: value1]
[key1:: [key2:: value2]]
becomes
{"key1": ["value1", "[key2:: value2]"]}
Example 4
[key1:: value1]
[key1:: [key2:: value2]]
[key1:: [key2:: value3]]
becomes
{"key1": ["value1", "[key2:: value2]", "[key2:: value3]"]}
The two options going forward as far as I see them are either
- Dataview plugin has no special handling and continues to treat them as strings and leaves it up to the user to handle them
- Dataview plugin looks for nested fields and parses those as well. Examples 3 and 4 would look like the following.
{"key1": ["value1", {"key2": "value2"}]}
{"key1": ["value1", {"key2": "value2"}, {"key2": "value3"}]}
I don't think it would be wise for the dataview plugin to try and merge the data more than this due to the ambiguity of how to merge dictionaries as well as the possibility of the list containing strings.
Agree on all points and will leave PR and other feedback to blacksmithgu.
As a more philosophical question, why use the inline keys over YAML frontmatter? YAML probably is the most terse way to describe nested objects.
What would be the best way then of "Links-as-Tags" usage? I use "Topics:: [[Technology]], [[Programming]]" etc, because I need/want what those linkified brackets provide(++simply: draws graph view lines) <3
(And yes, putting [[Programming]] nested under [[Technology]] would be a wonder - this entire issue sounds worthy. Good luck, skilled codefolk.)
Wasn't this merged recently? @gentlegiantJGC can you confirm?
The pull request to fix the renderer has been merged but nothing more has been said about how obsidian should internally handle these fields. https://github.com/blacksmithgu/obsidian-dataview/issues/1270#issuecomment-1192581468
I assume you meant how Dataview should handle these fields. IMO better to leave it as a string for now since this is a fairly niche case where we can safely expect the user to parse it themselves. I'm closing it and we can revisit it at a later time unless you/blacksmithgu think a plugin-side fix is better.
Imo nested metadata is quite common and would be pretty handy for usage. Ideally it would be handled something like =this.key1.key2
though of course I don't know how hard it would be to implement.
@mayurankv I understand the request but sadly I've seen it probably 2 out of every 100 cases. As always, anyone else is free to create a PR.
As a more philosophical question, why use the inline keys over YAML frontmatter? YAML probably is the most terse way to describe nested objects.
@blacksmithgu Obsidian doesn't parse linked notes inside YAML front matter. The links don't show up in mentions or graph view. Here's long conversation about this on the Obsidian forums: Wikilinks in YAML front matter
So if I understand correctly there currently is no way that anything inline and nested like Sub:: Prop:: Value
can be parsed, yes?
That is a shame as I recently moved to a system with more inline metadata because it allows for linking using wiki links. Being able to nest there as well would be very helpful.
I would love to help implement this feature as I am a programmer by trade but have very little knowledge of neither TypeScript nor this project. TypeScript I can figure out but dataview is a rather complex project. If someone more knowledge-able about dataview could give me just a few pointers (like where the inline metadata is actually parsed) and rough estimate of the complexity I would however be happy to attempt extending the existing implementation.