@realfavicongenerator/check-favicon 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const node_html_parser_1 = require("node-html-parser");
13
+ const types_1 = require("./types");
14
+ const touch_icon_1 = require("./touch-icon");
15
+ const test_helper_1 = require("./test-helper");
16
+ const helper_1 = require("./helper");
17
+ const runCheckTouchIconTitleTest = (headFragment_1, output_1, ...args_1) => __awaiter(void 0, [headFragment_1, output_1, ...args_1], void 0, function* (headFragment, output, fetchDatabase = {}) {
18
+ const root = headFragment ? (0, node_html_parser_1.parse)(headFragment) : null;
19
+ const result = yield (0, touch_icon_1.checkTouchIconTitle)('https://example.com/', root, (0, test_helper_1.testFetcher)(fetchDatabase));
20
+ const filteredMessages = result.messages.map(m => ({ status: m.status, id: m.id }));
21
+ expect({
22
+ messages: filteredMessages,
23
+ appTitle: result.appTitle
24
+ }).toEqual(output);
25
+ });
26
+ test('checkTouchIconTitle - noHead', () => __awaiter(void 0, void 0, void 0, function* () {
27
+ yield runCheckTouchIconTitleTest(null, { messages: [{
28
+ status: types_1.CheckerStatus.Error,
29
+ id: types_1.MessageId.noHead,
30
+ }] });
31
+ }));
32
+ test('checkTouchIconTitle - noTouchWebAppTitle', () => __awaiter(void 0, void 0, void 0, function* () {
33
+ yield runCheckTouchIconTitleTest('<title>Some text</title>', { messages: [{
34
+ status: types_1.CheckerStatus.Warning,
35
+ id: types_1.MessageId.noTouchWebAppTitle,
36
+ }] });
37
+ }));
38
+ test('checkTouchIconTitle - multipleTouchWebAppTitles', () => __awaiter(void 0, void 0, void 0, function* () {
39
+ yield runCheckTouchIconTitleTest(`
40
+ <meta name="apple-mobile-web-app-title" content="First title">
41
+ <meta name="apple-mobile-web-app-title" content="Second title">
42
+ `, { messages: [{
43
+ status: types_1.CheckerStatus.Error,
44
+ id: types_1.MessageId.multipleTouchWebAppTitles,
45
+ }] });
46
+ }));
47
+ test('checkTouchIconTitle - touchWebAppTitleDeclared', () => __awaiter(void 0, void 0, void 0, function* () {
48
+ yield runCheckTouchIconTitleTest(`
49
+ <meta name="apple-mobile-web-app-title" content="The App Name">
50
+ `, { messages: [{
51
+ status: types_1.CheckerStatus.Ok,
52
+ id: types_1.MessageId.touchWebAppTitleDeclared,
53
+ }], appTitle: 'The App Name' });
54
+ }));
55
+ const runCheckTouchIconTest = (headFragment_2, output_2, ...args_2) => __awaiter(void 0, [headFragment_2, output_2, ...args_2], void 0, function* (headFragment, output, fetchDatabase = {}) {
56
+ const root = headFragment ? (0, node_html_parser_1.parse)(headFragment) : null;
57
+ const result = yield (0, touch_icon_1.checkTouchIconIcon)('https://example.com/', root, (0, test_helper_1.testFetcher)(fetchDatabase));
58
+ const filteredMessages = result.messages.map(m => ({ status: m.status, id: m.id }));
59
+ expect({
60
+ messages: filteredMessages,
61
+ touchIcon: result.touchIcon
62
+ }).toEqual(Object.assign(Object.assign({}, output), { touchIcon: output.touchIcon || null }));
63
+ });
64
+ test('checkTouchIcon - noHead', () => __awaiter(void 0, void 0, void 0, function* () {
65
+ yield runCheckTouchIconTest(null, { messages: [{
66
+ status: types_1.CheckerStatus.Error,
67
+ id: types_1.MessageId.noHead,
68
+ }] });
69
+ }));
70
+ test('checkTouchIcon - noTouchIcon', () => __awaiter(void 0, void 0, void 0, function* () {
71
+ yield runCheckTouchIconTest('<title>Some text</title>', { messages: [{
72
+ status: types_1.CheckerStatus.Error,
73
+ id: types_1.MessageId.noTouchIcon,
74
+ }] });
75
+ }));
76
+ test('checkTouchIcon - touchIconWithSize', () => __awaiter(void 0, void 0, void 0, function* () {
77
+ yield runCheckTouchIconTest(`
78
+ <link rel="apple-touch-icon" sizes="152x152" href="some-other-icon.png">
79
+ `, { messages: [{
80
+ status: types_1.CheckerStatus.Ok,
81
+ id: types_1.MessageId.touchIconDeclared,
82
+ }, {
83
+ status: types_1.CheckerStatus.Warning,
84
+ id: types_1.MessageId.touchIconWithSize,
85
+ }] }, {
86
+ 'https://example.com/some-other-icon.png': {
87
+ status: 200,
88
+ contentType: 'image/png',
89
+ readableStream: null
90
+ }
91
+ });
92
+ }));
93
+ test('checkTouchIcon - multipleTouchIcon - no size', () => __awaiter(void 0, void 0, void 0, function* () {
94
+ yield runCheckTouchIconTest(`
95
+ <link rel="apple-touch-icon" href="some-icon.png">
96
+ <link rel="apple-touch-icon" href="some-other-icon.png">
97
+ `, { messages: [{
98
+ status: types_1.CheckerStatus.Ok,
99
+ id: types_1.MessageId.touchIconDeclared,
100
+ }, {
101
+ status: types_1.CheckerStatus.Error,
102
+ id: types_1.MessageId.duplicatedTouchIconSizes,
103
+ }] }, {
104
+ 'https://example.com/some-icon.png': {
105
+ status: 200,
106
+ contentType: 'image/png',
107
+ readableStream: null
108
+ },
109
+ 'https://example.com/some-other-icon.png': {
110
+ status: 200,
111
+ contentType: 'image/png',
112
+ readableStream: null
113
+ }
114
+ });
115
+ }));
116
+ test('checkTouchIcon - multipleTouchIcon - specific size', () => __awaiter(void 0, void 0, void 0, function* () {
117
+ yield runCheckTouchIconTest(`
118
+ <link rel="apple-touch-icon" sizes="180x180" href="some-icon.png">
119
+ <link rel="apple-touch-icon" sizes="180x180" href="some-other-icon.png">
120
+ `, { messages: [{
121
+ status: types_1.CheckerStatus.Ok,
122
+ id: types_1.MessageId.touchIconDeclared,
123
+ }, {
124
+ status: types_1.CheckerStatus.Warning,
125
+ id: types_1.MessageId.touchIconWithSize,
126
+ }, {
127
+ status: types_1.CheckerStatus.Error,
128
+ id: types_1.MessageId.duplicatedTouchIconSizes,
129
+ }] }, {
130
+ 'https://example.com/some-icon.png': {
131
+ status: 200,
132
+ contentType: 'image/png',
133
+ readableStream: null
134
+ },
135
+ 'https://example.com/some-other-icon.png': {
136
+ status: 200,
137
+ contentType: 'image/png',
138
+ readableStream: null
139
+ }
140
+ });
141
+ }));
142
+ test('checkTouchIcon - touchIconWithSize', () => __awaiter(void 0, void 0, void 0, function* () {
143
+ yield runCheckTouchIconTest(`
144
+ <link rel="apple-touch-icon" sizes="180x180" href="some-other-icon.png">
145
+ `, { messages: [{
146
+ status: types_1.CheckerStatus.Ok,
147
+ id: types_1.MessageId.touchIconDeclared,
148
+ }, {
149
+ status: types_1.CheckerStatus.Warning,
150
+ id: types_1.MessageId.touchIconWithSize,
151
+ }] }, {
152
+ 'https://example.com/some-other-icon.png': {
153
+ status: 200,
154
+ contentType: 'image/png',
155
+ readableStream: null
156
+ }
157
+ });
158
+ }));
159
+ const testIcon = './fixtures/180x180.png';
160
+ test('checkTouchIcon - Regular case', () => __awaiter(void 0, void 0, void 0, function* () {
161
+ yield runCheckTouchIconTest(`
162
+ <link rel="apple-touch-icon" href="some-other-icon.png">
163
+ `, { messages: [{
164
+ status: types_1.CheckerStatus.Ok,
165
+ id: types_1.MessageId.touchIconDeclared,
166
+ }, {
167
+ status: types_1.CheckerStatus.Ok,
168
+ id: types_1.MessageId.touchIconDownloadable,
169
+ }, {
170
+ status: types_1.CheckerStatus.Ok,
171
+ id: types_1.MessageId.touchIconSquare
172
+ }], touchIcon: (0, helper_1.bufferToDataUrl)(yield (0, helper_1.readableStreamToBuffer)(yield (0, helper_1.filePathToReadableStream)(testIcon)), 'image/png')
173
+ }, {
174
+ 'https://example.com/some-other-icon.png': {
175
+ status: 200,
176
+ contentType: 'image/png',
177
+ readableStream: yield (0, helper_1.filePathToReadableStream)(testIcon)
178
+ }
179
+ });
180
+ }));
181
+ test('getDuplicatedSizes', () => {
182
+ // No duplicates
183
+ expect((0, touch_icon_1.getDuplicatedSizes)([])).toEqual([]);
184
+ expect((0, touch_icon_1.getDuplicatedSizes)([undefined])).toEqual([]);
185
+ expect((0, touch_icon_1.getDuplicatedSizes)(['180x180'])).toEqual([]);
186
+ expect((0, touch_icon_1.getDuplicatedSizes)([undefined, '180x180'])).toEqual([]);
187
+ // Duplicates
188
+ expect((0, touch_icon_1.getDuplicatedSizes)(['152x152', '180x180', '180x180'])).toEqual(['180x180']);
189
+ expect((0, touch_icon_1.getDuplicatedSizes)([undefined, '180x180', undefined, undefined])).toEqual([undefined]);
190
+ expect((0, touch_icon_1.getDuplicatedSizes)([
191
+ '152x152', '180x180', '152x152', undefined, '152x152', undefined
192
+ ])).toEqual([
193
+ '152x152', undefined
194
+ ]);
195
+ });
@@ -0,0 +1,113 @@
1
+ export declare enum CheckerStatus {
2
+ Ok = "Ok",
3
+ Error = "Error",
4
+ Warning = "Warning"
5
+ }
6
+ export declare enum MessageId {
7
+ noHead = 0,
8
+ svgFaviconDeclared = 1,
9
+ noSvgFavicon = 2,
10
+ multipleSvgFavicons = 3,
11
+ noSvgFaviconHref = 4,
12
+ svgFavicon404 = 5,
13
+ svgFaviconCannotGet = 6,
14
+ svgFaviconDownloadable = 7,
15
+ svgFaviconSquare = 8,
16
+ svgFaviconNotSquare = 9,
17
+ noIcoFavicon = 10,
18
+ multipleIcoFavicons = 11,
19
+ icoFaviconDeclared = 12,
20
+ noIcoFaviconHref = 13,
21
+ icoFavicon404 = 14,
22
+ icoFaviconCannotGet = 15,
23
+ icoFaviconDownloadable = 16,
24
+ icoFaviconExtraSizes = 17,
25
+ icoFaviconMissingSizes = 18,
26
+ icoFaviconExpectedSizes = 19,
27
+ noDesktopPngFavicon = 20,
28
+ no48x48DesktopPngFavicon = 21,
29
+ desktopPngFaviconDeclared = 22,
30
+ noDesktopPngFaviconHref = 23,
31
+ desktopPngFaviconCannotGet = 24,
32
+ desktopPngFaviconDownloadable = 25,
33
+ desktopPngFavicon404 = 26,
34
+ desktopPngFaviconWrongSize = 27,
35
+ desktopPngFaviconRightSize = 28,
36
+ noTouchWebAppTitle = 29,
37
+ multipleTouchWebAppTitles = 30,
38
+ emptyTouchWebAppTitle = 31,
39
+ touchWebAppTitleDeclared = 32,
40
+ noTouchIcon = 33,
41
+ duplicatedTouchIconSizes = 34,
42
+ touchIconWithSize = 35,
43
+ touchIconDeclared = 36,
44
+ noTouchIconHref = 37,
45
+ touchIcon404 = 38,
46
+ touchIconCannotGet = 39,
47
+ touchIconDownloadable = 40,
48
+ touchIconSquare = 41,
49
+ touchIcon180x180 = 42,
50
+ touchIconNotSquare = 43,
51
+ touchIconWrongSize = 44,
52
+ noManifest = 45,
53
+ noManifestHref = 46,
54
+ manifest404 = 47,
55
+ manifestCannotGet = 48,
56
+ manifestInvalidJson = 49,
57
+ manifestName = 50,
58
+ noManifestName = 51,
59
+ manifestShortName = 52,
60
+ noManifestShortName = 53,
61
+ manifestBackgroundColor = 54,
62
+ noManifestBackgroundColor = 55,
63
+ manifestThemeColor = 56,
64
+ noManifestThemeColor = 57,
65
+ noManifestIcons = 58,
66
+ noManifestIcon = 59,
67
+ manifestIconDeclared = 60,
68
+ manifestIconCannotGet = 61,
69
+ manifestIconDownloadable = 62,
70
+ manifestIcon404 = 63,
71
+ manifestIconNoHref = 64,
72
+ manifestIconNotSquare = 65,
73
+ manifestIconRightSize = 66,
74
+ manifestIconSquare = 67,
75
+ manifestIconWrongSize = 68
76
+ }
77
+ export type CheckerMessage = {
78
+ status: CheckerStatus;
79
+ id: MessageId;
80
+ text: string;
81
+ };
82
+ export type FetchResponse = {
83
+ status: number;
84
+ contentType: string | null;
85
+ readableStream?: ReadableStream | null;
86
+ };
87
+ export type Fetcher = (url: string, contentType?: string) => Promise<FetchResponse>;
88
+ export type DesktopFaviconReport = {
89
+ messages: CheckerMessage[];
90
+ icon: string | null;
91
+ };
92
+ export type TouchIconTitleReport = {
93
+ messages: CheckerMessage[];
94
+ appTitle?: string;
95
+ };
96
+ export type TouchIconIconReport = {
97
+ messages: CheckerMessage[];
98
+ touchIcon: string | null;
99
+ };
100
+ export type WebManifestReport = {
101
+ messages: CheckerMessage[];
102
+ name?: string;
103
+ shortName?: string;
104
+ backgroundColor?: string;
105
+ themeColor?: string;
106
+ icon: string | null;
107
+ };
108
+ export type FaviconReport = {
109
+ desktop: DesktopFaviconReport;
110
+ touchIcon: TouchIconReport;
111
+ webAppManifest: WebManifestReport;
112
+ };
113
+ export type TouchIconReport = TouchIconIconReport & TouchIconTitleReport;
package/dist/types.js ADDED
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MessageId = exports.CheckerStatus = void 0;
4
+ var CheckerStatus;
5
+ (function (CheckerStatus) {
6
+ CheckerStatus["Ok"] = "Ok";
7
+ CheckerStatus["Error"] = "Error";
8
+ CheckerStatus["Warning"] = "Warning";
9
+ })(CheckerStatus || (exports.CheckerStatus = CheckerStatus = {}));
10
+ var MessageId;
11
+ (function (MessageId) {
12
+ MessageId[MessageId["noHead"] = 0] = "noHead";
13
+ MessageId[MessageId["svgFaviconDeclared"] = 1] = "svgFaviconDeclared";
14
+ MessageId[MessageId["noSvgFavicon"] = 2] = "noSvgFavicon";
15
+ MessageId[MessageId["multipleSvgFavicons"] = 3] = "multipleSvgFavicons";
16
+ MessageId[MessageId["noSvgFaviconHref"] = 4] = "noSvgFaviconHref";
17
+ MessageId[MessageId["svgFavicon404"] = 5] = "svgFavicon404";
18
+ MessageId[MessageId["svgFaviconCannotGet"] = 6] = "svgFaviconCannotGet";
19
+ MessageId[MessageId["svgFaviconDownloadable"] = 7] = "svgFaviconDownloadable";
20
+ MessageId[MessageId["svgFaviconSquare"] = 8] = "svgFaviconSquare";
21
+ MessageId[MessageId["svgFaviconNotSquare"] = 9] = "svgFaviconNotSquare";
22
+ MessageId[MessageId["noIcoFavicon"] = 10] = "noIcoFavicon";
23
+ MessageId[MessageId["multipleIcoFavicons"] = 11] = "multipleIcoFavicons";
24
+ MessageId[MessageId["icoFaviconDeclared"] = 12] = "icoFaviconDeclared";
25
+ MessageId[MessageId["noIcoFaviconHref"] = 13] = "noIcoFaviconHref";
26
+ MessageId[MessageId["icoFavicon404"] = 14] = "icoFavicon404";
27
+ MessageId[MessageId["icoFaviconCannotGet"] = 15] = "icoFaviconCannotGet";
28
+ MessageId[MessageId["icoFaviconDownloadable"] = 16] = "icoFaviconDownloadable";
29
+ MessageId[MessageId["icoFaviconExtraSizes"] = 17] = "icoFaviconExtraSizes";
30
+ MessageId[MessageId["icoFaviconMissingSizes"] = 18] = "icoFaviconMissingSizes";
31
+ MessageId[MessageId["icoFaviconExpectedSizes"] = 19] = "icoFaviconExpectedSizes";
32
+ MessageId[MessageId["noDesktopPngFavicon"] = 20] = "noDesktopPngFavicon";
33
+ MessageId[MessageId["no48x48DesktopPngFavicon"] = 21] = "no48x48DesktopPngFavicon";
34
+ MessageId[MessageId["desktopPngFaviconDeclared"] = 22] = "desktopPngFaviconDeclared";
35
+ MessageId[MessageId["noDesktopPngFaviconHref"] = 23] = "noDesktopPngFaviconHref";
36
+ MessageId[MessageId["desktopPngFaviconCannotGet"] = 24] = "desktopPngFaviconCannotGet";
37
+ MessageId[MessageId["desktopPngFaviconDownloadable"] = 25] = "desktopPngFaviconDownloadable";
38
+ MessageId[MessageId["desktopPngFavicon404"] = 26] = "desktopPngFavicon404";
39
+ MessageId[MessageId["desktopPngFaviconWrongSize"] = 27] = "desktopPngFaviconWrongSize";
40
+ MessageId[MessageId["desktopPngFaviconRightSize"] = 28] = "desktopPngFaviconRightSize";
41
+ MessageId[MessageId["noTouchWebAppTitle"] = 29] = "noTouchWebAppTitle";
42
+ MessageId[MessageId["multipleTouchWebAppTitles"] = 30] = "multipleTouchWebAppTitles";
43
+ MessageId[MessageId["emptyTouchWebAppTitle"] = 31] = "emptyTouchWebAppTitle";
44
+ MessageId[MessageId["touchWebAppTitleDeclared"] = 32] = "touchWebAppTitleDeclared";
45
+ MessageId[MessageId["noTouchIcon"] = 33] = "noTouchIcon";
46
+ MessageId[MessageId["duplicatedTouchIconSizes"] = 34] = "duplicatedTouchIconSizes";
47
+ MessageId[MessageId["touchIconWithSize"] = 35] = "touchIconWithSize";
48
+ MessageId[MessageId["touchIconDeclared"] = 36] = "touchIconDeclared";
49
+ MessageId[MessageId["noTouchIconHref"] = 37] = "noTouchIconHref";
50
+ MessageId[MessageId["touchIcon404"] = 38] = "touchIcon404";
51
+ MessageId[MessageId["touchIconCannotGet"] = 39] = "touchIconCannotGet";
52
+ MessageId[MessageId["touchIconDownloadable"] = 40] = "touchIconDownloadable";
53
+ MessageId[MessageId["touchIconSquare"] = 41] = "touchIconSquare";
54
+ MessageId[MessageId["touchIcon180x180"] = 42] = "touchIcon180x180";
55
+ MessageId[MessageId["touchIconNotSquare"] = 43] = "touchIconNotSquare";
56
+ MessageId[MessageId["touchIconWrongSize"] = 44] = "touchIconWrongSize";
57
+ MessageId[MessageId["noManifest"] = 45] = "noManifest";
58
+ MessageId[MessageId["noManifestHref"] = 46] = "noManifestHref";
59
+ MessageId[MessageId["manifest404"] = 47] = "manifest404";
60
+ MessageId[MessageId["manifestCannotGet"] = 48] = "manifestCannotGet";
61
+ MessageId[MessageId["manifestInvalidJson"] = 49] = "manifestInvalidJson";
62
+ MessageId[MessageId["manifestName"] = 50] = "manifestName";
63
+ MessageId[MessageId["noManifestName"] = 51] = "noManifestName";
64
+ MessageId[MessageId["manifestShortName"] = 52] = "manifestShortName";
65
+ MessageId[MessageId["noManifestShortName"] = 53] = "noManifestShortName";
66
+ MessageId[MessageId["manifestBackgroundColor"] = 54] = "manifestBackgroundColor";
67
+ MessageId[MessageId["noManifestBackgroundColor"] = 55] = "noManifestBackgroundColor";
68
+ MessageId[MessageId["manifestThemeColor"] = 56] = "manifestThemeColor";
69
+ MessageId[MessageId["noManifestThemeColor"] = 57] = "noManifestThemeColor";
70
+ MessageId[MessageId["noManifestIcons"] = 58] = "noManifestIcons";
71
+ MessageId[MessageId["noManifestIcon"] = 59] = "noManifestIcon";
72
+ MessageId[MessageId["manifestIconDeclared"] = 60] = "manifestIconDeclared";
73
+ MessageId[MessageId["manifestIconCannotGet"] = 61] = "manifestIconCannotGet";
74
+ MessageId[MessageId["manifestIconDownloadable"] = 62] = "manifestIconDownloadable";
75
+ MessageId[MessageId["manifestIcon404"] = 63] = "manifestIcon404";
76
+ MessageId[MessageId["manifestIconNoHref"] = 64] = "manifestIconNoHref";
77
+ MessageId[MessageId["manifestIconNotSquare"] = 65] = "manifestIconNotSquare";
78
+ MessageId[MessageId["manifestIconRightSize"] = 66] = "manifestIconRightSize";
79
+ MessageId[MessageId["manifestIconSquare"] = 67] = "manifestIconSquare";
80
+ MessageId[MessageId["manifestIconWrongSize"] = 68] = "manifestIconWrongSize";
81
+ })(MessageId || (exports.MessageId = MessageId = {}));
@@ -0,0 +1,4 @@
1
+ import { HTMLElement } from "node-html-parser";
2
+ import { Fetcher, WebManifestReport } from "./types";
3
+ export declare const checkWebAppManifest: (baseUrl: string, head: HTMLElement | null, fetcher?: Fetcher) => Promise<WebManifestReport>;
4
+ export declare const checkWebManifestFile: (manifest: any, baseUrl: string, fetcher: Fetcher) => Promise<WebManifestReport>;
@@ -0,0 +1,262 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ 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);
15
+ 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); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.checkWebManifestFile = exports.checkWebAppManifest = void 0;
20
+ const types_1 = require("./types");
21
+ const helper_1 = require("./helper");
22
+ 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) {
23
+ const messages = [];
24
+ let name = undefined;
25
+ let shortName = undefined;
26
+ let backgroundColor = undefined;
27
+ let themeColor = undefined;
28
+ let icon = null;
29
+ if (!head) {
30
+ messages.push({
31
+ status: types_1.CheckerStatus.Error,
32
+ id: types_1.MessageId.noHead,
33
+ text: 'No <head> element'
34
+ });
35
+ return { messages, name, shortName, backgroundColor, themeColor, icon };
36
+ }
37
+ const manifestMarkup = head.querySelectorAll("link[rel='manifest']");
38
+ if (manifestMarkup.length === 0) {
39
+ messages.push({
40
+ status: types_1.CheckerStatus.Error,
41
+ id: types_1.MessageId.noManifest,
42
+ text: 'No web app manifest'
43
+ });
44
+ return { messages, name, shortName, backgroundColor, themeColor, icon };
45
+ }
46
+ const href = manifestMarkup[0].getAttribute('href');
47
+ if (!href) {
48
+ messages.push({
49
+ status: types_1.CheckerStatus.Error,
50
+ id: types_1.MessageId.noManifestHref,
51
+ text: 'The web app manifest markup has no `href` attribute'
52
+ });
53
+ return { messages, name, shortName, backgroundColor, themeColor, icon };
54
+ }
55
+ const manifestUrl = (0, helper_1.mergeUrlAndPath)(baseUrl, href);
56
+ const manifest = yield fetcher(manifestUrl, 'application/json');
57
+ if (manifest.status === 404) {
58
+ messages.push({
59
+ status: types_1.CheckerStatus.Error,
60
+ id: types_1.MessageId.manifest404,
61
+ text: `The web app manifest at \`${href}\` is not found`
62
+ });
63
+ return { messages, name, shortName, backgroundColor, themeColor, icon };
64
+ }
65
+ else if (manifest.status >= 300 || !manifest.readableStream) {
66
+ messages.push({
67
+ status: types_1.CheckerStatus.Error,
68
+ id: types_1.MessageId.manifestCannotGet,
69
+ text: `Cannot get the web app manifest at \`${href}\` (${manifest.status} error)`
70
+ });
71
+ return { messages, name, shortName, backgroundColor, themeColor, icon };
72
+ }
73
+ let parsedManifest;
74
+ try {
75
+ parsedManifest = yield readableStreamToJson(manifest.readableStream);
76
+ }
77
+ catch (e) {
78
+ messages.push({
79
+ status: types_1.CheckerStatus.Error,
80
+ id: types_1.MessageId.manifestInvalidJson,
81
+ text: `Cannot parse the web app manifest at \`${href}\``
82
+ });
83
+ return { messages, name, shortName, backgroundColor, themeColor, icon };
84
+ }
85
+ const manifestReport = yield (0, exports.checkWebManifestFile)(parsedManifest, manifestUrl, fetcher);
86
+ return Object.assign(Object.assign({}, manifestReport), { messages: messages.concat(manifestReport.messages) });
87
+ });
88
+ exports.checkWebAppManifest = checkWebAppManifest;
89
+ const readableStreamToJson = (stream) => __awaiter(void 0, void 0, void 0, function* () {
90
+ const reader = stream.getReader();
91
+ const decoder = new TextDecoder();
92
+ let result = '';
93
+ while (true) {
94
+ const { done, value } = yield reader.read();
95
+ if (done) {
96
+ break;
97
+ }
98
+ result += decoder.decode(value);
99
+ }
100
+ return JSON.parse(result);
101
+ });
102
+ const checkWebManifestFile = (manifest, baseUrl, fetcher) => __awaiter(void 0, void 0, void 0, function* () {
103
+ var _a, e_1, _b, _c;
104
+ const messages = [];
105
+ let icon = null;
106
+ const name = manifest.name || undefined;
107
+ if (!name) {
108
+ messages.push({
109
+ status: types_1.CheckerStatus.Error,
110
+ id: types_1.MessageId.noManifestName,
111
+ text: 'The web app manifest has no `name`'
112
+ });
113
+ }
114
+ else {
115
+ messages.push({
116
+ status: types_1.CheckerStatus.Ok,
117
+ id: types_1.MessageId.manifestName,
118
+ text: `The web app manifest has the name "${name}"`
119
+ });
120
+ }
121
+ const shortName = manifest.short_name || undefined;
122
+ if (!shortName) {
123
+ messages.push({
124
+ status: types_1.CheckerStatus.Error,
125
+ id: types_1.MessageId.noManifestShortName,
126
+ text: 'The web app manifest has no `short_name`'
127
+ });
128
+ }
129
+ else {
130
+ messages.push({
131
+ status: types_1.CheckerStatus.Ok,
132
+ id: types_1.MessageId.manifestShortName,
133
+ text: `The web app manifest has the short name "${shortName}"`
134
+ });
135
+ }
136
+ const backgroundColor = manifest.background_color || undefined;
137
+ if (!backgroundColor) {
138
+ messages.push({
139
+ status: types_1.CheckerStatus.Error,
140
+ id: types_1.MessageId.noManifestBackgroundColor,
141
+ text: 'The web app manifest has no `background_color`'
142
+ });
143
+ }
144
+ else {
145
+ messages.push({
146
+ status: types_1.CheckerStatus.Ok,
147
+ id: types_1.MessageId.manifestBackgroundColor,
148
+ text: `The web app manifest has the background color \`${backgroundColor}\``
149
+ });
150
+ }
151
+ const themeColor = manifest.theme_color || undefined;
152
+ if (!themeColor) {
153
+ messages.push({
154
+ status: types_1.CheckerStatus.Error,
155
+ id: types_1.MessageId.noManifestThemeColor,
156
+ text: 'The web app manifest has no `theme_color`'
157
+ });
158
+ }
159
+ else {
160
+ messages.push({
161
+ status: types_1.CheckerStatus.Ok,
162
+ id: types_1.MessageId.manifestThemeColor,
163
+ text: `The web app manifest has the theme color \`${themeColor}\``
164
+ });
165
+ }
166
+ const icons = manifest.icons;
167
+ if (!icons || !Array.isArray(icons) || icons.length === 0) {
168
+ messages.push({
169
+ status: types_1.CheckerStatus.Error,
170
+ id: types_1.MessageId.noManifestIcons,
171
+ text: 'The web app manifest has no `icons`'
172
+ });
173
+ return { messages, name, shortName, backgroundColor, themeColor, icon };
174
+ }
175
+ try {
176
+ for (var _d = true, _e = __asyncValues([192, 512]), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
177
+ _c = _f.value;
178
+ _d = false;
179
+ const size = _c;
180
+ const iconEntry = icons.find((icon) => icon.sizes === `${size}x${size}`);
181
+ if (!iconEntry) {
182
+ messages.push({
183
+ status: types_1.CheckerStatus.Error,
184
+ id: types_1.MessageId.noManifestIcon,
185
+ text: `The web app manifest has no ${size}x${size} icon`
186
+ });
187
+ }
188
+ else {
189
+ messages.push({
190
+ status: types_1.CheckerStatus.Ok,
191
+ id: types_1.MessageId.manifestIconDeclared,
192
+ text: `The web app manifest has a ${size}x${size} icon`
193
+ });
194
+ const iconUrl = (0, helper_1.mergeUrlAndPath)(baseUrl, iconEntry.src);
195
+ const processor = {
196
+ cannotGet: (status) => {
197
+ messages.push({
198
+ status: types_1.CheckerStatus.Error,
199
+ id: types_1.MessageId.manifestIconCannotGet,
200
+ text: `The ${size}x${size} icon cannot be fetched (${status})`
201
+ });
202
+ },
203
+ downloadable: () => {
204
+ messages.push({
205
+ status: types_1.CheckerStatus.Ok,
206
+ id: types_1.MessageId.manifestIconDownloadable,
207
+ text: `The ${size}x${size} icon is downloadable`
208
+ });
209
+ },
210
+ icon404: () => {
211
+ messages.push({
212
+ status: types_1.CheckerStatus.Error,
213
+ id: types_1.MessageId.manifestIcon404,
214
+ text: `The ${size}x${size} icon is not found`
215
+ });
216
+ },
217
+ noHref: () => {
218
+ messages.push({
219
+ status: types_1.CheckerStatus.Error,
220
+ id: types_1.MessageId.manifestIconNoHref,
221
+ text: `The ${size}x${size} icon has no \`href\` attribute`
222
+ });
223
+ },
224
+ notSquare: () => {
225
+ messages.push({
226
+ status: types_1.CheckerStatus.Error,
227
+ id: types_1.MessageId.manifestIconNotSquare,
228
+ text: `The ${size}x${size} icon is not square`
229
+ });
230
+ },
231
+ rightSize: () => {
232
+ messages.push({
233
+ status: types_1.CheckerStatus.Ok,
234
+ id: types_1.MessageId.manifestIconRightSize,
235
+ text: `The ${size}x${size} icon has the right size`
236
+ });
237
+ },
238
+ square: () => {
239
+ // Ignore this, just check the size
240
+ },
241
+ wrongSize: (actualSize) => {
242
+ messages.push({
243
+ status: types_1.CheckerStatus.Error,
244
+ id: types_1.MessageId.manifestIconWrongSize,
245
+ text: `The ${size}x${size} icon has the wrong size (${actualSize})`
246
+ });
247
+ }
248
+ };
249
+ icon = yield (0, helper_1.checkIcon)(iconUrl, processor, fetcher, iconEntry.type || (0, helper_1.pathToMimeType)(iconEntry.src), size);
250
+ }
251
+ }
252
+ }
253
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
254
+ finally {
255
+ try {
256
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
257
+ }
258
+ finally { if (e_1) throw e_1.error; }
259
+ }
260
+ return { messages, name, shortName, backgroundColor, themeColor, icon };
261
+ });
262
+ exports.checkWebManifestFile = checkWebManifestFile;
@@ -0,0 +1 @@
1
+ export {};