UNPKG

@realfavicongenerator/check-favicon

Version:

Check the favicon of a website

263 lines (262 loc) 11.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 __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.checkWebAppManifestFile = exports.checkWebAppManifest = void 0; const types_1 = require("./types"); const helper_1 = require("./helper"); const checkWebAppManifest = (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 = []; let name = undefined; let shortName = undefined; let backgroundColor = undefined; let themeColor = undefined; let icon = null; if (!head) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noHead, text: 'No <head> element' }); return { messages, name, shortName, backgroundColor, themeColor, icon }; } const manifestMarkup = head.querySelectorAll("link[rel='manifest']"); if (manifestMarkup.length === 0) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noManifest, text: 'No web app manifest' }); return { messages, name, shortName, backgroundColor, themeColor, icon }; } const href = manifestMarkup[0].getAttribute('href'); if (!href) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noManifestHref, text: 'The web app manifest markup has no `href` attribute' }); return { messages, name, shortName, backgroundColor, themeColor, icon }; } const manifestUrl = (0, helper_1.mergeUrlAndPath)(baseUrl, href); const manifest = yield fetcher(manifestUrl, 'application/json'); if (manifest.status === 404) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.manifest404, text: `The web app manifest at \`${href}\` is not found` }); return { messages, name, shortName, backgroundColor, themeColor, icon }; } else if (manifest.status >= 300 || !manifest.readableStream) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.manifestCannotGet, text: `Cannot get the web app manifest at \`${href}\` (${manifest.status} error)` }); return { messages, name, shortName, backgroundColor, themeColor, icon }; } let parsedManifest; try { parsedManifest = yield readableStreamToJson(manifest.readableStream); } catch (e) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.manifestInvalidJson, text: `Cannot parse the web app manifest at \`${href}\`` }); return { messages, name, shortName, backgroundColor, themeColor, icon }; } const manifestReport = yield (0, exports.checkWebAppManifestFile)(parsedManifest, manifestUrl, fetcher); return Object.assign(Object.assign({}, manifestReport), { messages: messages.concat(manifestReport.messages) }); }); exports.checkWebAppManifest = checkWebAppManifest; const readableStreamToJson = (stream) => __awaiter(void 0, void 0, void 0, function* () { const reader = stream.getReader(); const decoder = new TextDecoder(); let result = ''; while (true) { const { done, value } = yield reader.read(); if (done) { break; } result += decoder.decode(value); } return JSON.parse(result); }); const checkWebAppManifestFile = (manifest, baseUrl, fetcher) => __awaiter(void 0, void 0, void 0, function* () { var _a, e_1, _b, _c; const messages = []; let icon = null; const name = manifest.name || undefined; if (!name) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noManifestName, text: 'The web app manifest has no `name`' }); } else { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.manifestName, text: `The web app manifest has the name "${name}"` }); } const shortName = manifest.short_name || undefined; if (!shortName) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noManifestShortName, text: 'The web app manifest has no `short_name`' }); } else { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.manifestShortName, text: `The web app manifest has the short name "${shortName}"` }); } const backgroundColor = manifest.background_color || undefined; if (!backgroundColor) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noManifestBackgroundColor, text: 'The web app manifest has no `background_color`' }); } else { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.manifestBackgroundColor, text: `The web app manifest has the background color \`${backgroundColor}\`` }); } const themeColor = manifest.theme_color || undefined; if (!themeColor) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noManifestThemeColor, text: 'The web app manifest has no `theme_color`' }); } else { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.manifestThemeColor, text: `The web app manifest has the theme color \`${themeColor}\`` }); } const icons = manifest.icons; if (!icons || !Array.isArray(icons) || icons.length === 0) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noManifestIcons, text: 'The web app manifest has no `icons`' }); return { messages, name, shortName, backgroundColor, themeColor, icon }; } try { for (var _d = true, _e = __asyncValues([192, 512]), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; const size = _c; const iconEntry = icons.find((icon) => icon.sizes === `${size}x${size}`); if (!iconEntry) { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.noManifestIcon, text: `The web app manifest has no ${size}x${size} icon` }); } else { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.manifestIconDeclared, text: `The web app manifest has a ${size}x${size} icon` }); const iconUrl = (0, helper_1.mergeUrlAndPath)(baseUrl, iconEntry.src); const processor = { cannotGet: (status) => { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.manifestIconCannotGet, text: `The ${size}x${size} icon cannot be fetched (${status})` }); }, downloadable: () => { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.manifestIconDownloadable, text: `The ${size}x${size} icon is downloadable` }); }, icon404: () => { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.manifestIcon404, text: `The ${size}x${size} icon is not found` }); }, noHref: () => { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.manifestIconNoHref, text: `The ${size}x${size} icon has no \`href\` attribute` }); }, notSquare: () => { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.manifestIconNotSquare, text: `The ${size}x${size} icon is not square` }); }, rightSize: () => { messages.push({ status: types_1.CheckerStatus.Ok, id: types_1.MessageId.manifestIconRightSize, text: `The ${size}x${size} icon has the right size` }); }, square: () => { // Ignore this, just check the size }, wrongSize: (actualSize) => { messages.push({ status: types_1.CheckerStatus.Error, id: types_1.MessageId.manifestIconWrongSize, text: `The ${size}x${size} icon has the wrong size (${actualSize})` }); } }; icon = yield (0, helper_1.checkIcon)(iconUrl, processor, fetcher, iconEntry.type || (0, helper_1.pathToMimeType)(iconEntry.src), size); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (!_d && !_a && (_b = _e.return)) yield _b.call(_e); } finally { if (e_1) throw e_1.error; } } return { messages, name, shortName, backgroundColor, themeColor, icon }; }); exports.checkWebAppManifestFile = checkWebAppManifestFile;