Need help with dataview query for getting quotes

Hello, I need your help for improving my dataview query for collecting my quotes.

My structure

I have files with the tag “Buch” which translates to “book” in English. In those files I fill out metadata for the book like the book title, the author of the book, my personal rating and so on.
I also collect quotes for that book in there using the following syntax:

> [!quote] Zitat
> (Zitat:: Quote)

(Meinung:: My own opinion about that quote)

This then basically looks like the following screenshot:

My dataview query

I now have a site that fetches for all quotes, my opinion on them and the book it’s coming from as a table. The query looks like the following (ignore the \ it’s just for not breaking the code block:

\```dataview
TABLE WITHOUT ID zitat AS Zitat, meinung AS Meinung, autor AS Autor
FROM #Buch AND -"Vorlagen"
WHERE zitat
\```

It also ignores the files in the folder “Vorlagen” where my templates are stored in.

My issue

The query itself works really good! It fetches all quotes from all my books as it should. However it is not rendered next to each other. So the quote, my opinion and the name of the book should be in the same row. It however renders the stuff ungrouped depending on how long the text is and puts everything under each other. (See screenshot to see what I mean).

Is there a way to render this correctly so that everything is in the same row, puts in empty space if i.e. the opinion on a quote is longer than the quote itself and then goes over to the next quote?

I’m not sure how I should organize my quotes otherwise because I don’t want to create a seperate file for each quote and I really like that structure. I just hate how it is being displayed using this query.

Thank you!

Not really, since both Zitat and Meinung are defined in the page context, and are not co-related to each other. There is nothing connecting a given quote with its meaning, as you’ve defined it currently. And since they’re not connected, you can’t really make the output as you want it.

My take on quotes are as follows:

  • I use tasks with status character q
  • I usually define the author within the quote text of that task
  • I use CSS to style the quotes to my liking
  • I often remove any inline fields present in the text
A complete note showcasing quotes and queries against them

Throughout the rest of this answer, I’ll refer to the queries and text of a note having the text below:

- [q] My most ingenious statement
	- Well, it's hard to come up with quotes
	- Even harder with a second point
- [q] When the going gets though, I'm gone [author:: me], (something:: hey there) 
	- This kind of a chicken approach to avoid issues

## The naive query
```dataview
TASK
WHERE file = this.file
  AND status = "q"
```

## With author either from task or note, and field removal
```dataview
TASK 
WHERE file = this.file AND status = "q"
FLATTEN regexreplace(text, "[\[\(][^\]\)]+[\]\)][, ]*", "") + ": _" + author + "_" as visual
```

## Using _dataviewjs_ to exclude subtasks

```dataviewjs
dv.taskList( dv.current().file.tasks
  .map(t => {
    if (t.children) t.children = [];
    t.visual = t.text.replace(/[\[\(][^\]\)]+[\]\)][, ]*/gm, "") +
               ", _" + (t.author ? t.author : dv.current().author) + "_"; 
    return t
  }), false )
```

## Table variant
```dataview
TABLE WITHOUT ID
  visual as Quote, task.children.text as Meaning, choice(task.author != null, task.author, author) as Author
WHERE file = this.file
FLATTEN file.tasks as task
FLATTEN regexreplace(task.text, "[\[\(][^\]\)]+[\]\)][, ]*", "") as visual
```

So for the sake of discussion here is my quotes list as it displays in the original source:
image

I’ve included the file’s author as “Someone”, and given “me” as the author in the second query. Using CSS I changed the checkbox into the quotation mark, and I think this looks rather good in the “origin” format.

Doing pure TASK queries on this text includes the “subtasks” or in this case the meanings of the quotes, as showcased below:

In the second variant I’ve excluded the fields, and added the author into the main text of the tasks in italics.

In order to remove the subtasks, we could either go to using dataviewjs retaining the backlinks which the pure task lists provides, or use a table to present the text from the tasks. These two queries do just that:

## Using _dataviewjs_ to exclude subtasks

```dataviewjs
dv.taskList( dv.current().file.tasks
  .map(t => {
    if (t.children) t.children = [];
    t.visual = t.text.replace(/[\[\(][^\]\)]+[\]\)][, ]*/gm, "") +
               ", _" + (t.author ? t.author : dv.current().author) + "_"; 
    return t
  }), false )
```

## Table variant
```dataview
TABLE WITHOUT ID
  visual as Quote, task.children.text as Meaning, choice(task.author != null, task.author, author) as Author
WHERE file = this.file
FLATTEN file.tasks as task
FLATTEN regexreplace(task.text, "[\[\(][^\]\)]+[\]\)][, ]*", "") as visual
```

In my test setup they display as:

This last table I reckon is maybe what you’re looking for, and this is a query which can accomplish that given that you change your definition of the quotes. You do however need to change from where you get the quotes, so you’ll need to replace either the WHERE file = this.file or the dv.current().files.tasks with something giving you a proper task list to further work on in the queries.

The CSS used to style these tasks

Below is the CSS used to style these task with the quotation mark in front, and with the margins slightly skewed to make it appear on the start of the line. Put the code below in a file like vault-folder/.obsidian/snippets/quoteTask.css, and enable it in Settings > Appearance > CSS snippets > quoteTask.css.

*** Common bits, and parts ***/
input[data-task="q"]:checked,
li[data-task="q"] > input:checked,
li[data-task="q"] > p > input:checked
{
  --checkbox-marker-color: transparent;
  border: none;
  border-radius: 0;
  background-image: none;
  background-color: currentColor;
  pointer-events: none;
  color: var(--color-green);
  -webkit-mask-size: var(--checkbox-icon);
  -webkit-mask-position: 50% 50%;
}

/* q - quote, remixicon: double-quotes-l */
input[data-task="q"]:checked,
li[data-task="q"] > input:checked,
li[data-task="q"] > p > input:checked {
  color: var(--text-faint);
  margin-left: -48px;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M4.583 17.321C3.553 16.227 3 15 3 13.011c0-3.5 2.457-6.637 6.03-8.188l.893 1.378c-3.335 1.804-3.987 4.145-4.247 5.621.537-.278 1.24-.375 1.929-.311 1.804.167 3.226 1.648 3.226 3.489a3.5 3.5 0 0 1-3.5 3.5c-1.073 0-2.099-.49-2.748-1.179zm10 0C13.553 16.227 13 15 13 13.011c0-3.5 2.457-6.637 6.03-8.188l.893 1.378c-3.335 1.804-3.987 4.145-4.247 5.621.537-.278 1.24-.375 1.929-.311 1.804.167 3.226 1.648 3.226 3.489a3.5 3.5 0 0 1-3.5 3.5c-1.073 0-2.099-.49-2.748-1.179z'/%3E%3C/svg%3E");
}

This is an extract of a more complete file where I define loads of custom statuses to decorate my tasks in my vaults. It should work as a standalone file too.

Thanks! This seems like a doable solution. The only thing that’s bugging me is that this solution uses tasks. Is it somehow possible to do it without tasks?

Why is it a problem that it uses tasks? That gives you, in the task query form, a link back to the origin of the quote which you’ll not get of you use the list context. In addition, you also can use the status character for styking and easy querying. Using a list context, you’ll need to use an extra field to group, and it not as easy to style, but it is doable.