-
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(icon-packs): support inline svg render
- add span warpper for all icon from `PackManager.getIcon`, including emoji - add `isc-emoji(img/svg)-icon` class for warpper - add new async method `PackManager.getSVGIcon`to get inline svg element or svg content close #23
- Loading branch information
Showing
15 changed files
with
320 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { FileSystemAdapter } from "obsidian"; | ||
import IconSC from "../isc-main"; | ||
import { FileIconData as FileIconDataType, FileIconInfo } from "./types"; | ||
import { extname } from "path"; | ||
|
||
import { getClsForIcon, getPacknNameFromId } from "./utils"; | ||
|
||
export class FileIconData implements FileIconDataType { | ||
static getData( | ||
id: string, | ||
path: string, | ||
plugin: IconSC, | ||
): FileIconData | null { | ||
const result = getPacknNameFromId(id); | ||
if (!result) return null; | ||
return new FileIconData(id, result.name, result.pack, path, plugin); | ||
} | ||
|
||
public type = "file" as const; | ||
public path: string; | ||
constructor( | ||
private _id: string, | ||
private _name: string, | ||
private _pack: string, | ||
path: string, | ||
private plugin: IconSC, | ||
) { | ||
this.path = path.trim(); | ||
} | ||
private get vault() { | ||
return this.plugin.app.vault; | ||
} | ||
|
||
public get id() { | ||
return this._id; | ||
} | ||
public get pack() { | ||
return this._pack; | ||
} | ||
public get name() { | ||
return this._name; | ||
} | ||
public get ext() { | ||
return extname(this.path); | ||
} | ||
public get fsPath() { | ||
if (this.vault.adapter instanceof FileSystemAdapter) { | ||
return this.vault.adapter.getFullPath(this.path); | ||
} else return null; | ||
} | ||
public get resourcePath() { | ||
return this.vault.adapter.getResourcePath(this.path); | ||
} | ||
public getDOM(svg: true): Promise<HTMLSpanElement>; | ||
public getDOM(svg: false): HTMLSpanElement; | ||
public getDOM(svg: boolean): Promise<HTMLSpanElement> | HTMLSpanElement { | ||
const el = createSpan({ cls: getClsForIcon(this) }); | ||
if (svg && this.ext === ".svg") { | ||
el.addClass("isc-svg-icon"); | ||
return (async () => { | ||
const svgEl = await this.plugin.fileIconCache.getIcon(this.path); | ||
if (svgEl) { | ||
el.append(svgEl); | ||
svgEl.addClass("isc-svg-icon"); | ||
} else { | ||
console.error("failed to get icon data for", this.path); | ||
} | ||
return el; | ||
})(); | ||
} else { | ||
el.addClass("isc-img-icon"); | ||
el.createEl("img", { attr: { src: this.resourcePath } }); | ||
return el; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { Stat } from "obsidian"; | ||
import type IconSC from "../isc-main"; | ||
|
||
declare global { | ||
const DOMPurify: typeof import("dompurify"); | ||
} | ||
|
||
interface IconCache { | ||
ctime: number; | ||
mtime: number; | ||
size: number; | ||
svg: SVGElement; | ||
} | ||
|
||
export default class FileIconCache { | ||
constructor(public plugin: IconSC) {} | ||
private get vault() { | ||
return this.plugin.app.vault; | ||
} | ||
private cache = new Map<string, IconCache>(); | ||
async getIcon(normalizedPath: string): Promise<SVGElement | null> { | ||
const stat = await this.vault.adapter.stat(normalizedPath); | ||
if (!stat || stat.type !== "file") return null; | ||
if (this.cache.has(normalizedPath)) { | ||
const cache = this.cache.get(normalizedPath)!; | ||
if ( | ||
cache.ctime === stat.ctime && | ||
cache.mtime === stat.mtime && | ||
cache.size === stat.size | ||
) { | ||
return cache.svg.cloneNode(true) as SVGElement; | ||
} | ||
} | ||
const svg = await this.readIntoCache(normalizedPath, stat); | ||
return svg.cloneNode(true) as SVGElement; | ||
} | ||
private async readIntoCache( | ||
normalizedPath: string, | ||
stat: Stat, | ||
): Promise<SVGElement> { | ||
const data = DOMPurify.sanitize( | ||
await this.vault.adapter.read(normalizedPath), | ||
), | ||
svg = new DOMParser().parseFromString(data, "image/svg+xml") | ||
.documentElement as unknown as SVGElement; | ||
this.cache.set(normalizedPath, { ...stat, svg }); | ||
return svg; | ||
} | ||
refresh() { | ||
const refresh = async (path: string) => { | ||
const stat = await this.vault.adapter.stat(path); | ||
if (!stat || stat.type !== "file") { | ||
this.cache.delete(path); | ||
} else { | ||
await this.readIntoCache(path, stat); | ||
} | ||
return path; | ||
}; | ||
return Promise.allSettled([...this.cache.keys()].map(refresh)); | ||
} | ||
clear() { | ||
this.cache.clear(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.