cleaning custom icons
This commit is contained in:
		
							parent
							
								
									d821344ade
								
							
						
					
					
						commit
						46a5d3d114
					
				| 
						 | 
					@ -1,8 +1,10 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import { setIcon, TFile } from 'obsidian'
 | 
					  import { setIcon, TFile } from 'obsidian'
 | 
				
			||||||
 | 
					  import { showExcerpt } from 'src/settings/utils'
 | 
				
			||||||
  import { onMount } from 'svelte'
 | 
					  import { onMount } from 'svelte'
 | 
				
			||||||
  import type { ResultNote } from '../globals'
 | 
					  import type { ResultNote } from '../globals'
 | 
				
			||||||
  import type LocatorPlugin from '../main'
 | 
					  import type LocatorPlugin from '../main'
 | 
				
			||||||
 | 
					  import { getDefaultIconSVG } from '../tools/icon-utils'
 | 
				
			||||||
  import {
 | 
					  import {
 | 
				
			||||||
    getExtension,
 | 
					    getExtension,
 | 
				
			||||||
    isFileCanvas,
 | 
					    isFileCanvas,
 | 
				
			||||||
| 
						 | 
					@ -12,15 +14,6 @@
 | 
				
			||||||
    pathWithoutFilename,
 | 
					    pathWithoutFilename,
 | 
				
			||||||
  } from '../tools/utils'
 | 
					  } from '../tools/utils'
 | 
				
			||||||
  import ResultItemContainer from './ResultItemContainer.svelte'
 | 
					  import ResultItemContainer from './ResultItemContainer.svelte'
 | 
				
			||||||
  // Import icon utility functions
 | 
					 | 
				
			||||||
  import { showExcerpt } from 'src/settings/utils'
 | 
					 | 
				
			||||||
  import {
 | 
					 | 
				
			||||||
    getDefaultIconSVG,
 | 
					 | 
				
			||||||
    getIconNameForPath,
 | 
					 | 
				
			||||||
    initializeIconPacks,
 | 
					 | 
				
			||||||
    loadIconData,
 | 
					 | 
				
			||||||
    loadIconSVG,
 | 
					 | 
				
			||||||
  } from '../tools/icon-utils'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let selected = false
 | 
					  export let selected = false
 | 
				
			||||||
  export let note: ResultNote
 | 
					  export let note: ResultNote
 | 
				
			||||||
| 
						 | 
					@ -29,19 +22,12 @@
 | 
				
			||||||
  let imagePath: string | null = null
 | 
					  let imagePath: string | null = null
 | 
				
			||||||
  let title = ''
 | 
					  let title = ''
 | 
				
			||||||
  let notePath = ''
 | 
					  let notePath = ''
 | 
				
			||||||
  let iconData = {}
 | 
					  const folderIconSVG = getDefaultIconSVG('folder')
 | 
				
			||||||
  let folderIconSVG: string | null = null
 | 
					  const fileIconSVG = getDefaultIconSVG(note.path)
 | 
				
			||||||
  let fileIconSVG: string | null = null
 | 
					 | 
				
			||||||
  let prefixToIconPack: { [prefix: string]: string } = {}
 | 
					 | 
				
			||||||
  let iconsPath: string
 | 
					 | 
				
			||||||
  let iconDataLoaded = false // Flag to indicate iconData is loaded
 | 
					  let iconDataLoaded = false // Flag to indicate iconData is loaded
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Initialize icon data and icon packs once when the component mounts
 | 
					  // Initialize icon data and icon packs once when the component mounts
 | 
				
			||||||
  onMount(async () => {
 | 
					  onMount(async () => {
 | 
				
			||||||
    iconData = await loadIconData(plugin)
 | 
					 | 
				
			||||||
    const iconPacks = await initializeIconPacks(plugin)
 | 
					 | 
				
			||||||
    prefixToIconPack = iconPacks.prefixToIconPack
 | 
					 | 
				
			||||||
    iconsPath = iconPacks.iconsPath
 | 
					 | 
				
			||||||
    iconDataLoaded = true // Set the flag after iconData is loaded
 | 
					    iconDataLoaded = true // Set the flag after iconData is loaded
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,40 +37,9 @@
 | 
				
			||||||
      // Update title and notePath before loading icons
 | 
					      // Update title and notePath before loading icons
 | 
				
			||||||
      title = note.displayTitle || note.basename
 | 
					      title = note.displayTitle || note.basename
 | 
				
			||||||
      notePath = pathWithoutFilename(note.path)
 | 
					      notePath = pathWithoutFilename(note.path)
 | 
				
			||||||
      await loadIcons()
 | 
					 | 
				
			||||||
    })()
 | 
					    })()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function loadIcons() {
 | 
					 | 
				
			||||||
    // Load folder icon
 | 
					 | 
				
			||||||
    const folderIconName = getIconNameForPath(notePath, iconData)
 | 
					 | 
				
			||||||
    if (folderIconName) {
 | 
					 | 
				
			||||||
      folderIconSVG = await loadIconSVG(
 | 
					 | 
				
			||||||
        folderIconName,
 | 
					 | 
				
			||||||
        plugin,
 | 
					 | 
				
			||||||
        iconsPath,
 | 
					 | 
				
			||||||
        prefixToIconPack
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      // Fallback to default folder icon
 | 
					 | 
				
			||||||
      folderIconSVG = getDefaultIconSVG('folder', plugin)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Load file icon
 | 
					 | 
				
			||||||
    const fileIconName = getIconNameForPath(note.path, iconData)
 | 
					 | 
				
			||||||
    if (fileIconName) {
 | 
					 | 
				
			||||||
      fileIconSVG = await loadIconSVG(
 | 
					 | 
				
			||||||
        fileIconName,
 | 
					 | 
				
			||||||
        plugin,
 | 
					 | 
				
			||||||
        iconsPath,
 | 
					 | 
				
			||||||
        prefixToIconPack
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      // Fallback to default icons based on file type
 | 
					 | 
				
			||||||
      fileIconSVG = getDefaultIconSVG(note.path, plugin)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Svelte action to render SVG content with dynamic updates
 | 
					  // Svelte action to render SVG content with dynamic updates
 | 
				
			||||||
  function renderSVG(node: HTMLElement, svgContent: string) {
 | 
					  function renderSVG(node: HTMLElement, svgContent: string) {
 | 
				
			||||||
    node.innerHTML = svgContent
 | 
					    node.innerHTML = svgContent
 | 
				
			||||||
| 
						 | 
					@ -163,9 +118,7 @@
 | 
				
			||||||
            title="The document above is embedded in this note" />
 | 
					            title="The document above is embedded in this note" />
 | 
				
			||||||
        {:else}
 | 
					        {:else}
 | 
				
			||||||
          <!-- File Icon -->
 | 
					          <!-- File Icon -->
 | 
				
			||||||
          {#if fileIconSVG}
 | 
					          <span class="omnisearch-result__icon" use:renderSVG={fileIconSVG} />
 | 
				
			||||||
            <span class="omnisearch-result__icon" use:renderSVG={fileIconSVG} />
 | 
					 | 
				
			||||||
          {/if}
 | 
					 | 
				
			||||||
        {/if}
 | 
					        {/if}
 | 
				
			||||||
        <span>
 | 
					        <span>
 | 
				
			||||||
          {@html plugin.textProcessor.highlightText(title, matchesTitle)}
 | 
					          {@html plugin.textProcessor.highlightText(title, matchesTitle)}
 | 
				
			||||||
| 
						 | 
					@ -191,9 +144,8 @@
 | 
				
			||||||
    {#if notePath}
 | 
					    {#if notePath}
 | 
				
			||||||
      <div class="omnisearch-result__folder-path">
 | 
					      <div class="omnisearch-result__folder-path">
 | 
				
			||||||
        <!-- Folder Icon -->
 | 
					        <!-- Folder Icon -->
 | 
				
			||||||
        {#if folderIconSVG}
 | 
					        <span class="omnisearch-result__icon" use:renderSVG={folderIconSVG} />
 | 
				
			||||||
          <span class="omnisearch-result__icon" use:renderSVG={folderIconSVG} />
 | 
					
 | 
				
			||||||
        {/if}
 | 
					 | 
				
			||||||
        <span>
 | 
					        <span>
 | 
				
			||||||
          {@html plugin.textProcessor.highlightText(notePath, matchesNotePath)}
 | 
					          {@html plugin.textProcessor.highlightText(notePath, matchesNotePath)}
 | 
				
			||||||
        </span>
 | 
					        </span>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,181 +1,12 @@
 | 
				
			||||||
import { getIcon, normalizePath } from 'obsidian'
 | 
					import { getIcon } from 'obsidian'
 | 
				
			||||||
import type LocatorPlugin from '../main'
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  isFileImage,
 | 
					 | 
				
			||||||
  isFilePDF,
 | 
					 | 
				
			||||||
  isFileCanvas,
 | 
					  isFileCanvas,
 | 
				
			||||||
  isFileExcalidraw,
 | 
					  isFileExcalidraw,
 | 
				
			||||||
  warnVerbose,
 | 
					  isFileImage,
 | 
				
			||||||
 | 
					  isFilePDF
 | 
				
			||||||
} from './utils'
 | 
					} from './utils'
 | 
				
			||||||
import { escapeHTML } from './text-processing'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IconPacks {
 | 
					export function getDefaultIconSVG(notePath: string): string {
 | 
				
			||||||
  prefixToIconPack: { [prefix: string]: string }
 | 
					 | 
				
			||||||
  iconsPath: string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function loadIconData(plugin: LocatorPlugin): Promise<any> {
 | 
					 | 
				
			||||||
  const app = plugin.app
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Check if the 'obsidian-icon-folder' plugin is installed and enabled
 | 
					 | 
				
			||||||
  // Casting 'app' to 'any' here to avoid TypeScript errors since 'plugins' might not be defined on 'App'
 | 
					 | 
				
			||||||
  const iconFolderPlugin = (app as any).plugins.getPlugin(
 | 
					 | 
				
			||||||
    'obsidian-icon-folder'
 | 
					 | 
				
			||||||
  )
 | 
					 | 
				
			||||||
  if (!iconFolderPlugin) {
 | 
					 | 
				
			||||||
    return {}
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const dataJsonPath = `${app.vault.configDir}/plugins/obsidian-icon-folder/data.json`
 | 
					 | 
				
			||||||
  try {
 | 
					 | 
				
			||||||
    const dataJsonContent = await app.vault.adapter.read(dataJsonPath)
 | 
					 | 
				
			||||||
    const rawIconData = JSON.parse(dataJsonContent)
 | 
					 | 
				
			||||||
    // Normalize keys
 | 
					 | 
				
			||||||
    const iconData: any = {}
 | 
					 | 
				
			||||||
    for (const key in rawIconData) {
 | 
					 | 
				
			||||||
      const normalizedKey = normalizePath(key)
 | 
					 | 
				
			||||||
      iconData[normalizedKey] = rawIconData[key]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return iconData
 | 
					 | 
				
			||||||
  } catch (e) {
 | 
					 | 
				
			||||||
    warnVerbose('Failed to read data.json:', e)
 | 
					 | 
				
			||||||
    return {}
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function initializeIconPacks(
 | 
					 | 
				
			||||||
  plugin: LocatorPlugin
 | 
					 | 
				
			||||||
): Promise<IconPacks> {
 | 
					 | 
				
			||||||
  // Add 'Li' prefix for Lucide icons
 | 
					 | 
				
			||||||
  const prefixToIconPack: { [prefix: string]: string } = { Li: 'lucide-icons' }
 | 
					 | 
				
			||||||
  let iconsPath = 'icons'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const app = plugin.app
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Access the obsidian-icon-folder plugin
 | 
					 | 
				
			||||||
  const iconFolderPlugin = (app as any).plugins.getPlugin(
 | 
					 | 
				
			||||||
    'obsidian-icon-folder'
 | 
					 | 
				
			||||||
  )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (iconFolderPlugin) {
 | 
					 | 
				
			||||||
    // Get the icons path from the plugin's settings
 | 
					 | 
				
			||||||
    const iconFolderSettings = iconFolderPlugin.settings
 | 
					 | 
				
			||||||
    iconsPath = iconFolderSettings?.iconPacksPath || 'icons'
 | 
					 | 
				
			||||||
    const iconsDir = `${app.vault.configDir}/${iconsPath}`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      const iconPackDirs = await app.vault.adapter.list(iconsDir)
 | 
					 | 
				
			||||||
      if (iconPackDirs.folders && iconPackDirs.folders.length > 0) {
 | 
					 | 
				
			||||||
        for (const folderPath of iconPackDirs.folders) {
 | 
					 | 
				
			||||||
          const pathParts = folderPath.split('/')
 | 
					 | 
				
			||||||
          const iconPackName = pathParts[pathParts.length - 1]
 | 
					 | 
				
			||||||
          const prefix = createIconPackPrefix(iconPackName)
 | 
					 | 
				
			||||||
          prefixToIconPack[prefix] = iconPackName
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } catch (e) {
 | 
					 | 
				
			||||||
      warnVerbose('Failed to list icon packs:', e)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return { prefixToIconPack, iconsPath }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function createIconPackPrefix(iconPackName: string): string {
 | 
					 | 
				
			||||||
  if (iconPackName.includes('-')) {
 | 
					 | 
				
			||||||
    const splitted = iconPackName.split('-')
 | 
					 | 
				
			||||||
    let result = splitted[0].charAt(0).toUpperCase()
 | 
					 | 
				
			||||||
    for (let i = 1; i < splitted.length; i++) {
 | 
					 | 
				
			||||||
      result += splitted[i].charAt(0).toLowerCase()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return result
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return (
 | 
					 | 
				
			||||||
    iconPackName.charAt(0).toUpperCase() + iconPackName.charAt(1).toLowerCase()
 | 
					 | 
				
			||||||
  )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function getIconNameForPath(path: string, iconData: any): string | null {
 | 
					 | 
				
			||||||
  const normalizedPath = normalizePath(path)
 | 
					 | 
				
			||||||
  const iconEntry = iconData[normalizedPath]
 | 
					 | 
				
			||||||
  if (iconEntry) {
 | 
					 | 
				
			||||||
    if (typeof iconEntry === 'string') {
 | 
					 | 
				
			||||||
      return iconEntry
 | 
					 | 
				
			||||||
    } else if (typeof iconEntry === 'object' && iconEntry.iconName) {
 | 
					 | 
				
			||||||
      return iconEntry.iconName
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return null
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function parseIconName(iconName: string): {
 | 
					 | 
				
			||||||
  prefix: string
 | 
					 | 
				
			||||||
  name: string
 | 
					 | 
				
			||||||
} {
 | 
					 | 
				
			||||||
  const prefixMatch = iconName.match(/^[A-Z][a-z]*/)
 | 
					 | 
				
			||||||
  if (prefixMatch) {
 | 
					 | 
				
			||||||
    const prefix = prefixMatch[0]
 | 
					 | 
				
			||||||
    const name = iconName.substring(prefix.length)
 | 
					 | 
				
			||||||
    return { prefix, name }
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    // No prefix, treat the entire iconName as the name
 | 
					 | 
				
			||||||
    return { prefix: '', name: iconName }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function loadIconSVG(
 | 
					 | 
				
			||||||
  iconName: string,
 | 
					 | 
				
			||||||
  plugin: LocatorPlugin,
 | 
					 | 
				
			||||||
  iconsPath: string,
 | 
					 | 
				
			||||||
  prefixToIconPack: { [prefix: string]: string }
 | 
					 | 
				
			||||||
): Promise<string | null> {
 | 
					 | 
				
			||||||
  const parsed = parseIconName(iconName)
 | 
					 | 
				
			||||||
  const { prefix, name } = parsed
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!prefix) {
 | 
					 | 
				
			||||||
    // No prefix, assume it's an emoji or text
 | 
					 | 
				
			||||||
    return `<span class="locator-result__icon--emoji">${escapeHTML(
 | 
					 | 
				
			||||||
      name
 | 
					 | 
				
			||||||
    )}</span>`
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const iconPackName = prefixToIconPack[prefix]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!iconPackName) {
 | 
					 | 
				
			||||||
    warnVerbose(`No icon pack found for prefix: ${prefix}`)
 | 
					 | 
				
			||||||
    return null
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (iconPackName === 'lucide-icons') {
 | 
					 | 
				
			||||||
    // Convert CamelCase to dash-case for Lucide icons
 | 
					 | 
				
			||||||
    const dashedName = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
 | 
					 | 
				
			||||||
    const iconEl = getIcon(dashedName)
 | 
					 | 
				
			||||||
    if (iconEl) {
 | 
					 | 
				
			||||||
      return iconEl.outerHTML
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      warnVerbose(`Lucide icon not found: ${dashedName}`)
 | 
					 | 
				
			||||||
      return null
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    if (!iconsPath) {
 | 
					 | 
				
			||||||
      warnVerbose('Icons path is not set. Cannot load icon SVG.')
 | 
					 | 
				
			||||||
      return null
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    const iconPath = `${plugin.app.vault.configDir}/${iconsPath}/${iconPackName}/${name}.svg`
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      const svgContent = await plugin.app.vault.adapter.read(iconPath)
 | 
					 | 
				
			||||||
      return svgContent
 | 
					 | 
				
			||||||
    } catch (e) {
 | 
					 | 
				
			||||||
      warnVerbose(`Failed to load icon SVG for ${iconName} at ${iconPath}:`, e)
 | 
					 | 
				
			||||||
      return null
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function getDefaultIconSVG(
 | 
					 | 
				
			||||||
  notePath: string,
 | 
					 | 
				
			||||||
  plugin: LocatorPlugin
 | 
					 | 
				
			||||||
): string {
 | 
					 | 
				
			||||||
  // Return SVG content for default icons based on file type
 | 
					  // Return SVG content for default icons based on file type
 | 
				
			||||||
  let iconName = 'file'
 | 
					  let iconName = 'file'
 | 
				
			||||||
  if (isFileImage(notePath)) {
 | 
					  if (isFileImage(notePath)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user