obsidian-dataview icon indicating copy to clipboard operation
obsidian-dataview copied to clipboard

Nested Inline Fields

Open gentlegiantJGC opened this issue 1 year ago • 12 comments

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 image

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)

gentlegiantJGC avatar Jul 20 '22 10:07 gentlegiantJGC

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.

AB1908 avatar Jul 20 '22 22:07 AB1908

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 avatar Jul 21 '22 00:07 blacksmithgu

@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.

AnnaKornfeldSimpson avatar Jul 21 '22 02:07 AnnaKornfeldSimpson

At that point, it's probably much better to write your own parser haha. See #967.

AB1908 avatar Jul 21 '22 07:07 AB1908

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.

gentlegiantJGC avatar Jul 21 '22 13:07 gentlegiantJGC

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-])

image

It seems to display correctly if you are using the same types of bracket.

[test:: [test:: [test:: 2020]]]
(test:: (test:: (test:: 2020)))

image

gentlegiantJGC avatar Jul 21 '22 17:07 gentlegiantJGC

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

gentlegiantJGC avatar Jul 21 '22 19:07 gentlegiantJGC

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

  1. Dataview plugin has no special handling and continues to treat them as strings and leaves it up to the user to handle them
  2. 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.

gentlegiantJGC avatar Jul 22 '22 13:07 gentlegiantJGC

Agree on all points and will leave PR and other feedback to blacksmithgu.

AB1908 avatar Jul 22 '22 13:07 AB1908

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.)

NohbdyAhtall avatar Aug 02 '22 00:08 NohbdyAhtall

Wasn't this merged recently? @gentlegiantJGC can you confirm?

AB1908 avatar Aug 05 '22 11:08 AB1908

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

gentlegiantJGC avatar Aug 05 '22 21:08 gentlegiantJGC

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.

AB1908 avatar Aug 26 '22 21:08 AB1908

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 avatar Oct 28 '22 18:10 mayurankv

@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.

AB1908 avatar Oct 28 '22 22:10 AB1908

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

charleshan avatar Feb 11 '23 06:02 charleshan

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.

BeCracked avatar Feb 23 '23 11:02 BeCracked