UNPKG

@realfavicongenerator/check-favicon

Version:
240 lines (239 loc) 10.6 kB
"use strict"; 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.checkDesktopFavicon = exports.checkPngFavicon = exports.checkSvgFaviconFile = exports.checkSvgFavicon = exports.PngFaviconFileSize = void 0; const types_1 = require("../types"); const sharp_1 = __importDefault(require("sharp")); const helper_1 = require("../helper"); const ico_1 = require("./ico"); exports.PngFaviconFileSize = 96; const checkSvgFavicon = (baseUrl_1, head_1, ...args_1) => __awaiter(void 0, [baseUrl_1, head_1, ...args_1], void 0, function* (baseUrl, head, fetcher = helper_1.fetchFetcher) { 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 svgs = head === null || head === void 0 ? void 0 : head.querySelectorAll("link[rel='icon'][type='image/svg+xml']"); if (svgs.length === 0) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noSvgFavicon, text: 'There is no SVG favicon' }); } else if (svgs.length > 1) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.multipleSvgFavicons, text: `There are ${svgs.length} SVG favicons` }); } else { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.svgFaviconDeclared, text: 'The SVG favicon is declared' }); const href = svgs[0].attributes.href; if (!href) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noSvgFaviconHref, text: 'The SVG markup has no href attribute' }); } else { const iconReport = yield (0, exports.checkSvgFaviconFile)(baseUrl, href, fetcher); return { messages: [...messages, ...iconReport.messages], icon: iconReport.icon }; } } return { messages, icon: { content: null, url: null, width: null, height: null } }; }); exports.checkSvgFavicon = checkSvgFavicon; const checkSvgFaviconFile = (baseUrl, url, fetcher) => __awaiter(void 0, void 0, void 0, function* () { const messages = []; const svgUrl = (0, helper_1.mergeUrlAndPath)(baseUrl, url); const res = yield fetcher(svgUrl, 'image/svg+xml'); let content; let width = null; let height = null; if (res.status === 404) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.svgFavicon404, text: `The SVG icon file \`${url}\` does not exist (404 error)` }); } else if (res.status >= 300) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.svgFaviconCannotGet, text: `Cannot get the SVG icon file at \`${url}\` (${res.status} error)` }); } else if (res.readableStream) { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.svgFaviconDownloadable, text: `The SVG favicon is accessible at \`${url}\`` }); content = yield (0, helper_1.readableStreamToString)(res.readableStream); const meta = yield (0, sharp_1.default)(Buffer.from(content)).metadata(); width = meta.width || null; height = meta.height || null; if (width && height && width !== height) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.svgFaviconNotSquare, text: `The SVG is not square (${width}x${height})` }); } else { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.svgFaviconSquare, text: `The SVG is square (${width}x${height})` }); } } return { messages, icon: { content: content ? yield (0, helper_1.bufferToDataUrl)(Buffer.from(content), 'image/svg+xml') : null, url: svgUrl, width, height } }; }); exports.checkSvgFaviconFile = checkSvgFaviconFile; const checkPngFavicon = (baseUrl_2, head_2, ...args_2) => __awaiter(void 0, [baseUrl_2, head_2, ...args_2], void 0, function* (baseUrl, head, fetcher = helper_1.fetchFetcher) { 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 icons = head === null || head === void 0 ? void 0 : head.querySelectorAll("link[rel='icon'][type='image/png']"); if (icons.length === 0) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noDesktopPngFavicon, text: 'There is no desktop PNG favicon' }); } else { const size = `${exports.PngFaviconFileSize}x${exports.PngFaviconFileSize}`; const sizedIconMarkup = icons.filter(icon => icon.attributes.sizes === size); if (sizedIconMarkup.length === 0) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.no96x96DesktopPngFavicon, text: `There is no ${size} desktop PNG favicon` }); } else { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.desktopPngFaviconDeclared, text: `The ${size} desktop PNG favicon is declared` }); const href = sizedIconMarkup[0].attributes.href; if (!href) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noDesktopPngFaviconHref, text: `The ${size} desktop favicon markup has no href attribute` }); } else { const iconUrl = (0, helper_1.mergeUrlAndPath)(baseUrl, href); const processor = { cannotGet: (httpStatus) => { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.desktopPngFaviconCannotGet, text: `Cannot get the ${size} desktop PNG favicon at \`${iconUrl}\` (${httpStatus} error)` }); }, downloadable: () => { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.desktopPngFaviconDownloadable, text: `The ${size} desktop PNG favicon is accessible` }); }, icon404: () => { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.desktopPngFavicon404, text: `The ${size} desktop PNG favicon does not exist (404 error)` }); }, notSquare: (width, height) => { }, // Ignore this message wrongSize: (widthHeight) => { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.desktopPngFaviconWrongSize, text: `The ${size} desktop PNG favicon has the wrong size (${widthHeight}x${widthHeight})` }); }, rightSize(widthHeight) { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.desktopPngFaviconRightSize, text: `The ${size} desktop PNG favicon has the right size` }); }, square: (widthHeight) => { }, // Ignore this message, noHref: () => { } // Ignore this message }; const icon = yield (0, helper_1.checkIcon)(iconUrl, processor, fetcher, icons[0].attributes.mimeType || 'image/png', exports.PngFaviconFileSize); return { messages, icon }; } } } return { messages, icon: { content: null, url: null, width: null, height: null } }; }); exports.checkPngFavicon = checkPngFavicon; const checkDesktopFavicon = (baseUrl_3, head_3, ...args_3) => __awaiter(void 0, [baseUrl_3, head_3, ...args_3], void 0, function* (baseUrl, head, fetcher = helper_1.fetchFetcher) { const svgReport = yield (0, exports.checkSvgFavicon)(baseUrl, head, fetcher); const pngReport = yield (0, exports.checkPngFavicon)(baseUrl, head, fetcher); const icoReport = yield (0, ico_1.checkIcoFavicon)(baseUrl, head, fetcher); return { messages: [...svgReport.messages, ...pngReport.messages, ...icoReport.messages], icon: pngReport.icon ? pngReport.icon.content : null, icons: { png: pngReport.icon, ico: icoReport.icon, svg: svgReport.icon } }; }); exports.checkDesktopFavicon = checkDesktopFavicon;