@@ -66,6 +66,12 @@ export async function collectFieldValuesRaw(
6666 fieldName : string ,
6767 filters : FieldFilter ,
6868) : Promise < Set < string > > {
69+ const normalizedFieldName = fieldName . trim ( ) . toLowerCase ( ) ;
70+ if ( normalizedFieldName === "tags" || normalizedFieldName === "tag" ) {
71+ const tagValues = await collectTagValues ( app , filters ) ;
72+ if ( tagValues . size > 0 ) return tagValues ;
73+ }
74+
6975 // Try Dataview when allowed; fall back to manual collection
7076 try {
7177 if ( ! filters . inline && DataviewIntegration . isAvailable ( app ) ) {
@@ -86,6 +92,113 @@ export async function collectFieldValuesRaw(
8692 return await collectFieldValuesManually ( app , fieldName , filters ) ;
8793}
8894
95+ async function collectTagValues ( app : App , filters : FieldFilter ) : Promise < Set < string > > {
96+ const hasFileFilters =
97+ Boolean ( filters . folder ) ||
98+ Boolean ( filters . tags ?. length ) ||
99+ Boolean ( filters . excludeFolders ?. length ) ||
100+ Boolean ( filters . excludeTags ?. length ) ||
101+ Boolean ( filters . excludeFiles ?. length ) ;
102+
103+ if ( ! hasFileFilters ) {
104+ const fromIndex = collectAllVaultTags ( app ) ;
105+ if ( fromIndex . size > 0 ) return fromIndex ;
106+ }
107+
108+ return await collectTagValuesFromFiles ( app , filters ) ;
109+ }
110+
111+ function collectAllVaultTags ( app : App ) : Set < string > {
112+ const values = new Set < string > ( ) ;
113+
114+ try {
115+ // @ts -expect-error - getTags exists in Obsidian but is not typed
116+ const tagObj = app . metadataCache . getTags ?.( ) as
117+ | Record < string , number >
118+ | undefined ;
119+
120+ if ( ! tagObj ) return values ;
121+
122+ for ( const rawTag of Object . keys ( tagObj ) ) {
123+ const cleaned = rawTag . startsWith ( "#" ) ? rawTag . substring ( 1 ) : rawTag ;
124+ const tag = cleaned . trim ( ) ;
125+ if ( tag ) values . add ( tag ) ;
126+ }
127+ } catch {
128+ // ignore and fall back to file-based collection
129+ }
130+
131+ return values ;
132+ }
133+
134+ async function collectTagValuesFromFiles (
135+ app : App ,
136+ filters : FieldFilter ,
137+ ) : Promise < Set < string > > {
138+ const rawValues = new Set < string > ( ) ;
139+
140+ let files = app . vault . getMarkdownFiles ( ) ;
141+ files = EnhancedFieldSuggestionFileFilter . filterFiles (
142+ files ,
143+ filters ,
144+ ( file : TFile ) => app . metadataCache . getFileCache ( file ) ,
145+ ) ;
146+
147+ const batchSize = 50 ;
148+ for ( let i = 0 ; i < files . length ; i += batchSize ) {
149+ const batch = files . slice ( i , i + batchSize ) ;
150+ const promises = batch . map ( async ( file ) => {
151+ const values = new Set < string > ( ) ;
152+ try {
153+ const metadataCache = app . metadataCache . getFileCache ( file ) ;
154+
155+ // Frontmatter tags
156+ const frontmatterTags : unknown = metadataCache ?. frontmatter ?. tags ;
157+ if ( frontmatterTags !== undefined && frontmatterTags !== null ) {
158+ const tags = Array . isArray ( frontmatterTags )
159+ ? frontmatterTags
160+ : [ frontmatterTags ] ;
161+
162+ for ( const tag of tags ) {
163+ const s = String ( tag ) . trim ( ) ;
164+ if ( s ) values . add ( s ) ;
165+ }
166+ }
167+
168+ // Frontmatter tag (singular)
169+ const frontmatterTag : unknown = metadataCache ?. frontmatter ?. tag ;
170+ if ( frontmatterTag !== undefined && frontmatterTag !== null ) {
171+ const tags = Array . isArray ( frontmatterTag )
172+ ? frontmatterTag
173+ : [ frontmatterTag ] ;
174+
175+ for ( const tag of tags ) {
176+ const s = String ( tag ) . trim ( ) ;
177+ if ( s ) values . add ( s ) ;
178+ }
179+ }
180+
181+ // Inline tags
182+ if ( metadataCache ?. tags ) {
183+ for ( const t of metadataCache . tags ) {
184+ const raw = String ( t . tag ?? "" ) . trim ( ) ;
185+ const tag = raw . startsWith ( "#" ) ? raw . substring ( 1 ) : raw ;
186+ if ( tag ) values . add ( tag ) ;
187+ }
188+ }
189+ } catch { }
190+ return values ;
191+ } ) ;
192+
193+ const batchResults = await Promise . all ( promises ) ;
194+ for ( const set of batchResults ) {
195+ for ( const v of set ) rawValues . add ( v ) ;
196+ }
197+ }
198+
199+ return rawValues ;
200+ }
201+
89202async function collectFieldValuesManually (
90203 app : App ,
91204 fieldName : string ,
0 commit comments