mirror of
https://github.com/Llewellynvdm/nativefier.git
synced 2024-11-16 01:37:07 +00:00
112 lines
3.1 KiB
TypeScript
112 lines
3.1 KiB
TypeScript
|
import * as path from 'path';
|
||
|
import { writeFile } from 'fs';
|
||
|
import { promisify } from 'util';
|
||
|
|
||
|
import * as gitCloud from 'gitcloud';
|
||
|
import * as pageIcon from 'page-icon';
|
||
|
|
||
|
import {
|
||
|
downloadFile,
|
||
|
getAllowedIconFormats,
|
||
|
getTempDir,
|
||
|
} from '../helpers/helpers';
|
||
|
import * as log from 'loglevel';
|
||
|
|
||
|
const writeFileAsync = promisify(writeFile);
|
||
|
|
||
|
const GITCLOUD_SPACE_DELIMITER = '-';
|
||
|
const GITCLOUD_URL = 'https://jiahaog.github.io/nativefier-icons/';
|
||
|
|
||
|
function getMaxMatchScore(iconWithScores: any[]): number {
|
||
|
const score = iconWithScores.reduce((maxScore, currentIcon) => {
|
||
|
const currentScore = currentIcon.score;
|
||
|
if (currentScore > maxScore) {
|
||
|
return currentScore;
|
||
|
}
|
||
|
return maxScore;
|
||
|
}, 0);
|
||
|
log.debug('Max icon match score:', score);
|
||
|
return score;
|
||
|
}
|
||
|
|
||
|
function getMatchingIcons(iconsWithScores: any[], maxScore: number): any[] {
|
||
|
return iconsWithScores
|
||
|
.filter((item) => item.score === maxScore)
|
||
|
.map((item) => ({ ...item, ext: path.extname(item.url) }));
|
||
|
}
|
||
|
|
||
|
function mapIconWithMatchScore(cloudIcons: any[], targetUrl: string): any {
|
||
|
const normalisedTargetUrl = targetUrl.toLowerCase();
|
||
|
return cloudIcons.map((item) => {
|
||
|
const itemWords = item.name.split(GITCLOUD_SPACE_DELIMITER);
|
||
|
const score = itemWords.reduce((currentScore, word) => {
|
||
|
if (normalisedTargetUrl.includes(word)) {
|
||
|
return currentScore + 1;
|
||
|
}
|
||
|
return currentScore;
|
||
|
}, 0);
|
||
|
|
||
|
return { ...item, score };
|
||
|
});
|
||
|
}
|
||
|
|
||
|
async function inferIconFromStore(
|
||
|
targetUrl: string,
|
||
|
platform: string,
|
||
|
): Promise<any> {
|
||
|
log.debug(`Inferring icon from store for ${targetUrl} on ${platform}`);
|
||
|
const allowedFormats = new Set(getAllowedIconFormats(platform));
|
||
|
|
||
|
const cloudIcons = await gitCloud(GITCLOUD_URL);
|
||
|
log.debug(`Got ${cloudIcons.length} icons from gitcloud`);
|
||
|
const iconWithScores = mapIconWithMatchScore(cloudIcons, targetUrl);
|
||
|
const maxScore = getMaxMatchScore(iconWithScores);
|
||
|
|
||
|
if (maxScore === 0) {
|
||
|
log.debug('No relevant icon in store.');
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
const iconsMatchingScore = getMatchingIcons(iconWithScores, maxScore);
|
||
|
const iconsMatchingExt = iconsMatchingScore.filter((icon) =>
|
||
|
allowedFormats.has(icon.ext),
|
||
|
);
|
||
|
const matchingIcon = iconsMatchingExt[0];
|
||
|
const iconUrl = matchingIcon && matchingIcon.url;
|
||
|
|
||
|
if (!iconUrl) {
|
||
|
log.debug('Could not infer icon from store');
|
||
|
return null;
|
||
|
}
|
||
|
return downloadFile(iconUrl);
|
||
|
}
|
||
|
|
||
|
export async function inferIcon(
|
||
|
targetUrl: string,
|
||
|
platform: string,
|
||
|
): Promise<string> {
|
||
|
log.debug(`Inferring icon for ${targetUrl} on ${platform}`);
|
||
|
const tmpDirPath = getTempDir('iconinfer');
|
||
|
|
||
|
let icon: { ext: string; data: Buffer } = await inferIconFromStore(
|
||
|
targetUrl,
|
||
|
platform,
|
||
|
);
|
||
|
if (!icon) {
|
||
|
const ext = platform === 'win32' ? '.ico' : '.png';
|
||
|
log.debug(`Trying to extract a ${ext} icon from the page.`);
|
||
|
icon = await pageIcon(targetUrl, { ext });
|
||
|
}
|
||
|
if (!icon) {
|
||
|
return null;
|
||
|
}
|
||
|
log.debug(`Got an icon from the page.`);
|
||
|
|
||
|
const iconPath = path.join(tmpDirPath, `/icon${icon.ext}`);
|
||
|
log.debug(
|
||
|
`Writing ${(icon.data.length / 1024).toFixed(1)} kb icon to ${iconPath}`,
|
||
|
);
|
||
|
await writeFileAsync(iconPath, icon.data);
|
||
|
return iconPath;
|
||
|
}
|