// source => icon data
const enhancerIconSets = new Map();
getAsync(notionIconsUrl + 'icons.json', (iconsData) => {
const data = JSON.parse(iconsData);
(data.icons || data).forEach((set) => {
enhancerIconSets.set(set.source, set);
});
});
// array
let customIconSets;
if (store().json) {
const customData = JSON.parse(fs.readFileSync(store().json));
customIconSets = customData.icons || customData;
}
// convert icons data into renderable
function loadIconSets() {
const iconSets = new DocumentFragment();
if (customIconSets) {
customIconSets.forEach((i) => {
iconSets.appendChild(renderIconSet(i));
});
// divider
iconSets.appendChild(createElement('
'));
}
if (enhancerIconSets.size > 0) {
enhancerIconSets.forEach((i, source) => {
// ignore removed icon sets
if (store().removedSets?.includes(source)) return;
i.sourceUrl = i.sourceUrl || notionIconsUrl + source;
iconSets.appendChild(renderIconSet(i, true));
});
}
return iconSets;
}
// returns icon set element
function renderIconSet(iconData, enhancerSet = false) {
const iconSet = createElement('');
try {
const author = iconData.author
? iconData.authorUrl
? ` by ${iconData.author}`
: ` by ${iconData.author}`
: '';
const toggle = createElement(`
${menuIcons.triangle}
${iconData.name}${author}
`);
const iconSetBody = createElement('');
iconSet.append(toggle, iconSetBody);
const promiseArray = [];
// render icons
for (let i = 0; i < (iconData.count || iconData.source.length); i++) {
const iconUrl = iconData.sourceUrl
? Array.isArray(iconData.source)
? `${iconData.sourceUrl}/${iconData.source[i]}.${iconData.extension}`
: `${iconData.sourceUrl}/${iconData.source}_${i}.${iconData.extension}`
: iconData.source[i];
const icon = createElement(``);
icon.innerHTML = enhancerSet
? // load sprite sheet
``
: `
`;
// add filters to filterMap
const filters = [];
if (iconData.filter) {
if (iconData.filter === 'source') {
const filename = iconUrl.match(/.*\/(.+?)\./);
if (filename?.length > 1) {
filters.push(...filename[1].split(/[ \-_]/));
}
} else if (Array.isArray(iconData.filter)) {
filters.push(...iconData.filter[i]);
}
icon.setAttribute('filter', filters.join(' '));
}
// add set name and author to filters
filters.push(...iconData.name.toLowerCase().split(' '));
if (iconData.author) filters.push(...iconData.author.toLowerCase().split(' '));
filterMap.set(icon, filters);
// make sure icons load
if (!enhancerSet) {
promiseArray.push(
new Promise((resolve, reject) => {
icon.firstChild.onload = resolve;
icon.firstChild.onerror = () => {
reject();
icon.classList.add('error');
icon.innerHTML = '!';
};
})
);
}
garbageCollector.push(icon);
icon.addEventListener('click', () => setPageIcon(iconUrl));
iconSetBody.appendChild(icon);
}
// hide spinner after all icons finish loading
(async () => {
const spinner = toggle.querySelector('.notion-icons--spinner'),
loadPromise = Promise.all(promiseArray);
loadPromise.then(
() => spinner.remove(),
() => {
iconSet.classList.add('alert');
spinner.remove();
}
);
})();
// add remove icon set button
if (enhancerSet) {
const removeButton = createElement(
`${menuIcons.remove}
`
);
removeButton.addEventListener('click', (e) => {
e.stopPropagation();
removeIconSet(iconData);
});
iconSet.querySelector('.notion-icons--actions').appendChild(removeButton);
}
// set up toggle
toggle.addEventListener('click', (e) => {
if (e.target.nodeName === 'A') return;
toggleIconSet(iconSet);
});
// hide by default?
if (store().hide) requestAnimationFrame(() => toggleIconSet(iconSet));
// tooltip
let timeout;
iconSetBody.addEventListener('mouseover', (e) => {
const el = e.target;
if (!el.hasAttribute('filter')) return;
document.querySelector('.notion-icons--tooltip')?.remove();
timeout = setTimeout(() => {
renderTooltip(el, el.getAttribute('filter'));
}, 300);
});
iconSetBody.addEventListener('mouseout', (e) => {
const el = e.target;
if (!el.hasAttribute('filter')) return;
document.querySelector('.notion-icons--tooltip')?.remove();
clearTimeout(timeout);
});
} catch (err) {
iconSet.classList.add('error');
iconSet.innerHTML = `Invalid Icon Set: ${iconData.name}`;
}
return iconSet;
}