Processing lists in Obsidian Web Clipper templates (to clip Gemini chats)

Hello everyone,

I’m posting a solution to my own question, thanks to a brilliant idea from @dawni who answered me in Obsidian’s Discord channel.

The core problem, as I suspected, is that the Web Clipper’s template language cannot map filters (like markdown or callout) over a list of elements.

The workaround is to not treat it as a list at all. Instead, you grab all the elements in order, join them into a single string, and then use a clever, two-step replace() chain.

The Working Template

Here is the final template code that works perfectly for me. (Big thanks to dawni, who suggested the replace chain idea, which I adapted slightly).

JavaScript

{{selectorHtml:*:is(user-query, model-response message-content) | join:"" | replace:("<message-content":"★Gemini said<message-content" , "<user-query ":"★You said<user-query ") | markdown | blockquote | replace:("> \n> ★Gemini said":"\n> [!gemini]- Answer" , "> ★You said":"\n> [!user]- Query") }}

How This “Hack” Works

This one-liner is doing a lot, so here’s the breakdown:

  • selectorHtml:*:is(user-query, model-response message-content) This uses the :is() CSS selector to grab all user queries and model response content (I’m using message-content specifically to ignore the model’s “thoughts” panel and other UI elements).
  • | join:"" This concatenates all the found HTML elements into one single, large HTML string.
  • | replace:("...","...") (Part 1 - The “Pre-Hack”) This is the first key step. Before converting to Markdown, it injects unique text markers (★Gemini said and ★You said) directly into the HTML string, right before the content starts.
  • | markdown | blockquote This converts the entire HTML string into Markdown and then wraps the whole thing in a blockquote. This is crucial because it prefixes every line with a > .
  • | replace:("...","...") (Part 2 - The “Post-Hack”) This is the final step. It now searches for the markers, which (thanks to the previous filter) now look like > ★You said. It replaces these markers with the properly formatted newlines and callout headers (\n> [!user]- Query).

In my case, I use [!user] and [!gemini] callout types, which I defined via Callout Manager to have proper icons (lucide-user and lucide-stars, respectively), and I add the - that makes the callout collapsed by default, but you can adapt that to your taste.

This method completely bypasses the list-processing limitation. I hope this is helpful for anyone else facing a similar issue!

6 Likes