/**
* Icons, for blocks.
*
* A block draws an icon from the same reference the rest of the app uses — `mdi:account-edit` — and
* gets it from this instance's own `/_icons`, which serves the part of the Iconify API protocol the
* frontend speaks. Nothing here reaches Iconify itself: the server is what decides whether an icon
* can be had, and an instance that is offline still answers for every icon it has been asked for
* before.
*
* Shared because more than one block needs it, and one cache across all of them means a page whose
* every row carries the same icon asks for it once.
*/
/** Icons already fetched, by `prefix:name`. Holds the promise, so concurrent callers share a request. */
const iconCache = new Map()
/**
* Fetch an icon as inline SVG.
*
* Inline rather than an `
` so the drawing takes the colour of whatever it sits in — Iconify's
* SVGs paint with `currentColor`, which an image cannot see. The instance serves them from its own
* `/_icons`, cached hard, so this is a local request.
*
* An empty string for anything that is not a `prefix:name` reference, an icon the server will not
* serve, or a request that failed: a missing icon is a row without one, not a row that breaks.
*
* @param {string} reference An Iconify reference, e.g. `mdi:home`.
* @returns {Promise} The SVG markup, or an empty string.
*/
export async function fetchIcon(reference) {
if (iconCache.has(reference)) {
return iconCache.get(reference)
}
const [prefix, name] = reference.split(':')
if (!prefix || !name) {
return ''
}
const promise = fetch(`/_icons/${encodeURIComponent(prefix)}/${encodeURIComponent(name)}.svg`)
.then((resp) => (resp.ok ? resp.text() : ''))
.catch(() => '')
iconCache.set(reference, promise)
return promise
}
/**
* The address an `img:` reference points at, or null for one that is not an image.
*
* The icon picker's other tab hands back `img:/_assets/icons/…`, which is a file to point an `
`
* at rather than an icon to resolve — so it is the caller's to draw, and its colour is its own.
*
* @param {string} reference
* @returns {string|null}
*/
export function iconImageUrl(reference) {
return reference.startsWith('img:') ? reference.slice(4) : null
}