@realfavicongenerator/check-favicon
Version:
Check the favicon of a website
140 lines (139 loc) • 5.96 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkIcoFavicon = exports.IcoFaviconSizes = void 0;
const types_1 = require("../types");
const helper_1 = require("../helper");
const decode_ico_1 = __importDefault(require("decode-ico"));
exports.IcoFaviconSizes = [48, 32, 16];
const checkIcoFavicon = (url, head, fetcher) => __awaiter(void 0, void 0, void 0, function* () {
const messages = [];
if (!head) {
messages.push({
status: types_1.CheckerStatus.Error,
id: types_1.MessageId.noHead,
text: 'No <head> element'
});
return {
messages,
icon: { content: null, url: null, width: null, height: null }
};
}
const icos = [
...head.querySelectorAll('link[rel="shortcut icon"]'),
...head.querySelectorAll('link[rel="icon"][type="image/x-icon"]')
];
let iconUrl = null;
let images;
if (icos.length === 0) {
messages.push({
status: types_1.CheckerStatus.Error,
id: types_1.MessageId.noIcoFavicon,
text: 'There is no ICO favicon'
});
}
else if (icos.length > 1) {
messages.push({
status: types_1.CheckerStatus.Error,
id: types_1.MessageId.multipleIcoFavicons,
text: `There are ${icos.length} ICO favicons`
});
}
else {
messages.push({
status: types_1.CheckerStatus.Ok,
id: types_1.MessageId.icoFaviconDeclared,
text: 'The ICO favicon is declared'
});
const href = icos[0].attributes.href;
if (!href) {
messages.push({
status: types_1.CheckerStatus.Error,
id: types_1.MessageId.noIcoFaviconHref,
text: 'The ICO markup has no href attribute'
});
}
else {
iconUrl = (0, helper_1.mergeUrlAndPath)(url, href);
const iconResponse = yield fetcher(iconUrl, 'image/x-icon');
if (iconResponse.status === 404) {
messages.push({
status: types_1.CheckerStatus.Error,
id: types_1.MessageId.icoFavicon404,
text: `ICO favicon not found at ${iconUrl}`
});
}
else if (iconResponse.status >= 300 || !iconResponse.readableStream) {
messages.push({
status: types_1.CheckerStatus.Error,
id: types_1.MessageId.icoFaviconCannotGet,
text: `Error fetching ICO favicon at ${iconUrl} (status ${iconResponse.status})`
});
}
else {
messages.push({
status: types_1.CheckerStatus.Ok,
id: types_1.MessageId.icoFaviconDownloadable,
text: 'ICO favicon found'
});
const iconBuffer = yield (0, helper_1.readableStreamToBuffer)(iconResponse.readableStream);
images = yield (0, decode_ico_1.default)(iconBuffer);
const imageSizes = images.map(image => `${image.width}x${image.height}`);
const expectedSizes = exports.IcoFaviconSizes.map(size => `${size}x${size}`);
const extraSizes = imageSizes.filter(size => !expectedSizes.includes(size));
if (extraSizes.length > 0) {
messages.push({
status: types_1.CheckerStatus.Warning,
id: types_1.MessageId.icoFaviconExtraSizes,
text: `Extra sizes found in ICO favicon: ${extraSizes.join(', ')}`
});
}
const missingSizes = expectedSizes.filter(size => !imageSizes.includes(size));
if (missingSizes.length > 0) {
messages.push({
status: types_1.CheckerStatus.Warning,
id: types_1.MessageId.icoFaviconMissingSizes,
text: `Missing sizes in ICO favicon: ${missingSizes.join(', ')}`
});
}
if (extraSizes.length === 0 && missingSizes.length === 0) {
messages.push({
status: types_1.CheckerStatus.Ok,
id: types_1.MessageId.icoFaviconExpectedSizes,
text: `The ICO favicon has the expected sizes (${imageSizes.join(', ')})`
});
}
}
}
}
let content = null;
const theIcon = {
content: null,
url: iconUrl,
width: null,
height: null
};
if (images) {
const image = images[0];
const mimeType = (image.type === "bmp") ? "image/bmp" : "image/png";
theIcon.content = yield (0, helper_1.bufferToDataUrl)(Buffer.from(image.data), mimeType);
theIcon.width = image.width;
theIcon.height = image.height;
}
return {
messages,
icon: theIcon,
};
});
exports.checkIcoFavicon = checkIcoFavicon;