esm7 / obsidian-map-view

Interactive map view for Obsidian.md
MIT License
546 stars 25 forks source link

Allow inline tags in filter suggestions #225

Closed therealbnut closed 3 months ago

therealbnut commented 4 months ago

Hi,

Thanks for making this plugin, it's a large part of why I'm using Obsidian!

I've been having issues with tags, and it turns out that my issue was that you need a tag defined at a file level to be able to query it, even if the tag is defined inline ([](geo:...) tag:inline).

If you do something like this:

---
locations: 
---
[Machu Picchu](geo:-13.2263308,-72.4973215) tag:place tag:incan
[Stonehenge](geo:51.178882,-1.826215) tag:place tag:celtic

The query filter will not suggest any of these tags, you can't type it manually either. As far as I can tell, this is because obsidian itself doesn't know these are tags.

This also doesn't work:

---
locations: 
---
[Machu Picchu](geo:-13.2263308,-72.4973215) #place #incan
[Stonehenge](geo:51.178882,-1.826215) #place #celtic

because map view applies those tags to every marker in the file. It also has duplicate entries of #place in the query suggestions. This otherwise appears to be the equivalent of this:

---
locations: 
tags:
  - place
  - incan
  - celtic
---
[Machu Picchu](geo:-13.2263308,-72.4973215)
[Stonehenge](geo:51.178882,-1.826215)

The only workaround I've found at the moment, is to make a new file like this:

---
tags:
  - place
  - incan
  - celtic

Which works, but there's a lot of redundancy it'd be nice to avoid.

I would love to be able to use the # syntax inline rather than tag:. I think it would be more intuitive. If that's not possible for some technical/conventional reason it would be great for Map View to find inline tags without them having to be tags Obsidian is aware of (#). Either way it seems like there has to be some tag redundancy to make obsidian aware of it if you use tag:, so it doesn't seem ideal.

I've had a look at the code, and I think the issue might be because this doesn't find inline tags: https://github.com/esm7/obsidian-map-view/blob/2b3be819067c2e2dd85418f61f8bd9a4f126ba7b/src/utils.ts#L272-L286

Unrealated, I think it would be much faster using a Set instead of an array, something like this:

 export function getAllTagNames(app: App): string[] {
-     let tags: string[] = [];
+     let tags = new Set<string>();
     const allFiles = app.vault.getMarkdownFiles();
     for (const file of allFiles) {
         const fileCache = app.metadataCache.getFileCache(file);
         const fileTagNames = getAllTags(fileCache) || [];
-        if (fileTagNames.length > 0) {
-            tags = tags.concat(
-                fileTagNames.filter((tagName) => tags.indexOf(tagName) < 0)
-            );
-        }
+        fileTagNames.forEach(name => tags.add(name));
     }
-    tags = tags.sort();
-    return tags;
+    return [...tags].sort();
}

I'm sorry, I had a look, but I don't know enough about javascript typescript or obsidian to suggest how to fix my issue. It probably depends heavily on your reasons for the current syntax anyway.

It's possible that all uses of obsidian.getAllTags have a similar issue, and you might need to look at them too. I tried repurposing code from getMarkersFromFileContent in getAllTagNames, but I couldn't get it to work.

Thanks for reading this!

esm7 commented 4 months ago

Great catch, will fix!

therealbnut commented 4 months ago

@esm7 thank you very much ❤️! Also, if you don’t mind my asking, I’m interested to know how come you use tag: instead of # in the inline tags? It seems like # would be much better supported, but I’m sure there’s a reason it’s not used.

esm7 commented 4 months ago

The reason is that using # is interpreted by Obsidian as a tag that belongs to the whole note, regardless of what line it is at, and we don't want that happening for "inline" tags.

esm7 commented 3 months ago

Added as part of the just-released 5.0.0.