@realfavicongenerator/check-favicon 0.0.1 → 0.0.2
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.
- package/README.md +26 -0
- package/dist/desktop/desktop.d.ts +7 -0
- package/dist/desktop/desktop.js +213 -0
- package/dist/desktop/desktop.test.d.ts +1 -0
- package/dist/desktop/desktop.test.js +97 -0
- package/dist/desktop/ico.d.ts +4 -0
- package/dist/desktop/ico.js +115 -0
- package/dist/helper.d.ts +23 -0
- package/dist/helper.js +189 -0
- package/dist/helper.test.d.ts +1 -0
- package/dist/helper.test.js +121 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +13 -0
- package/dist/test-helper.d.ts +4 -0
- package/dist/test-helper.js +22 -0
- package/dist/touch-icon.d.ts +6 -0
- package/dist/touch-icon.js +187 -0
- package/dist/touch-icon.test.d.ts +1 -0
- package/dist/touch-icon.test.js +195 -0
- package/dist/types.d.ts +113 -0
- package/dist/types.js +81 -0
- package/dist/web-manifest.d.ts +4 -0
- package/dist/web-manifest.js +262 -0
- package/dist/web-manifest.test.d.ts +1 -0
- package/dist/web-manifest.test.js +172 -0
- package/package.json +6 -3
- package/src/desktop/desktop.test.ts +1 -1
- package/src/desktop/desktop.ts +2 -2
- package/src/desktop/ico.ts +1 -1
- package/src/helper.ts +33 -1
- package/src/index.ts +15 -160
- package/src/test-helper.ts +1 -1
- package/src/touch-icon.test.ts +1 -1
- package/src/touch-icon.ts +2 -2
- package/src/types.ts +129 -0
- package/src/web-manifest.test.ts +1 -1
- package/src/web-manifest.ts +2 -2
- package/tsconfig.json +2 -2
|
@@ -0,0 +1,172 @@
|
|
|
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 __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const node_html_parser_1 = __importDefault(require("node-html-parser"));
|
|
16
|
+
const types_1 = require("./types");
|
|
17
|
+
const web_manifest_1 = require("./web-manifest");
|
|
18
|
+
const test_helper_1 = require("./test-helper");
|
|
19
|
+
const helper_1 = require("./helper");
|
|
20
|
+
const filterOutput = (report) => (Object.assign(Object.assign({}, report), { messages: report.messages.map(m => ({ status: m.status, id: m.id })) }));
|
|
21
|
+
const runCheckTouchIconTitleTest = (headFragment_1, output_1, ...args_1) => __awaiter(void 0, [headFragment_1, output_1, ...args_1], void 0, function* (headFragment, output, fetchDatabase = {}) {
|
|
22
|
+
const root = headFragment ? (0, node_html_parser_1.default)(headFragment) : null;
|
|
23
|
+
const result = yield (0, web_manifest_1.checkWebManifest)('https://example.com/', root, (0, test_helper_1.testFetcher)(fetchDatabase));
|
|
24
|
+
expect(filterOutput(result)).toEqual(Object.assign({ name: undefined, shortName: undefined, backgroundColor: undefined, themeColor: undefined, icon: null }, output));
|
|
25
|
+
});
|
|
26
|
+
test('checkWebManifest - 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('checkWebManifest - noManifest', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
33
|
+
yield runCheckTouchIconTitleTest('<title>Hey</title>', { messages: [{
|
|
34
|
+
status: types_1.CheckerStatus.Error,
|
|
35
|
+
id: types_1.MessageId.noManifest,
|
|
36
|
+
}] });
|
|
37
|
+
}));
|
|
38
|
+
test('checkWebManifest - noManifestHref', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
+
yield runCheckTouchIconTitleTest('<link rel="manifest" />', { messages: [{
|
|
40
|
+
status: types_1.CheckerStatus.Error,
|
|
41
|
+
id: types_1.MessageId.noManifestHref,
|
|
42
|
+
}] });
|
|
43
|
+
}));
|
|
44
|
+
test('checkWebManifest - manifest404', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
|
+
yield runCheckTouchIconTitleTest('<link rel="manifest" href="not-found.json" />', { messages: [{
|
|
46
|
+
status: types_1.CheckerStatus.Error,
|
|
47
|
+
id: types_1.MessageId.manifest404,
|
|
48
|
+
}] });
|
|
49
|
+
}));
|
|
50
|
+
test('checkWebManifest - manifestCannotGet', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
+
yield runCheckTouchIconTitleTest('<link rel="manifest" href="/error.json" />', { messages: [{
|
|
52
|
+
status: types_1.CheckerStatus.Error,
|
|
53
|
+
id: types_1.MessageId.manifestCannotGet,
|
|
54
|
+
}] }, {
|
|
55
|
+
'https://example.com/error.json': {
|
|
56
|
+
status: 500,
|
|
57
|
+
contentType: 'application/json',
|
|
58
|
+
readableStream: null
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}));
|
|
62
|
+
test('checkWebManifest - manifestInvalidJson', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
|
+
yield runCheckTouchIconTitleTest('<link rel="manifest" href="/bad-manifest.json" />', { messages: [{
|
|
64
|
+
status: types_1.CheckerStatus.Error,
|
|
65
|
+
id: types_1.MessageId.manifestInvalidJson,
|
|
66
|
+
}] }, {
|
|
67
|
+
'https://example.com/bad-manifest.json': {
|
|
68
|
+
status: 200,
|
|
69
|
+
contentType: 'application/json',
|
|
70
|
+
readableStream: stringToReadableStream('{ bad JSON }')
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}));
|
|
74
|
+
const stringToReadableStream = (str) => {
|
|
75
|
+
const stream = new ReadableStream({
|
|
76
|
+
start(controller) {
|
|
77
|
+
controller.enqueue(new TextEncoder().encode(str));
|
|
78
|
+
controller.close();
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return stream;
|
|
82
|
+
};
|
|
83
|
+
test('checkWebManifestFile - Missing fields', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
84
|
+
const report = yield (0, web_manifest_1.checkWebManifestFile)({
|
|
85
|
+
name: null,
|
|
86
|
+
short_name: null,
|
|
87
|
+
background_color: null,
|
|
88
|
+
theme_color: null,
|
|
89
|
+
icons: []
|
|
90
|
+
}, 'https://example.com/', (0, test_helper_1.testFetcher)({}));
|
|
91
|
+
expect(filterOutput(report)).toEqual({
|
|
92
|
+
messages: [{
|
|
93
|
+
status: types_1.CheckerStatus.Error,
|
|
94
|
+
id: types_1.MessageId.noManifestName,
|
|
95
|
+
}, {
|
|
96
|
+
status: types_1.CheckerStatus.Error,
|
|
97
|
+
id: types_1.MessageId.noManifestShortName,
|
|
98
|
+
}, {
|
|
99
|
+
status: types_1.CheckerStatus.Error,
|
|
100
|
+
id: types_1.MessageId.noManifestBackgroundColor,
|
|
101
|
+
}, {
|
|
102
|
+
status: types_1.CheckerStatus.Error,
|
|
103
|
+
id: types_1.MessageId.noManifestThemeColor,
|
|
104
|
+
}, {
|
|
105
|
+
status: types_1.CheckerStatus.Error,
|
|
106
|
+
id: types_1.MessageId.noManifestIcons,
|
|
107
|
+
}],
|
|
108
|
+
name: undefined,
|
|
109
|
+
shortName: undefined,
|
|
110
|
+
backgroundColor: undefined,
|
|
111
|
+
themeColor: undefined,
|
|
112
|
+
icon: null
|
|
113
|
+
});
|
|
114
|
+
}));
|
|
115
|
+
const testIcon192 = './fixtures/192x192.png';
|
|
116
|
+
const testIcon512 = './fixtures/512x512.png';
|
|
117
|
+
test('checkWebManifestFile - Everything is fine', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
118
|
+
const report = yield (0, web_manifest_1.checkWebManifestFile)({
|
|
119
|
+
name: 'My long name',
|
|
120
|
+
short_name: 'Short!',
|
|
121
|
+
background_color: '#123456',
|
|
122
|
+
theme_color: '#abcdef',
|
|
123
|
+
icons: [
|
|
124
|
+
{ src: '/icon-192.png', sizes: '192x192', type: 'image/png' },
|
|
125
|
+
{ src: '/icon-512.png', sizes: '512x512', type: 'image/png' }
|
|
126
|
+
]
|
|
127
|
+
}, 'https://example.com/', (0, test_helper_1.testFetcher)({
|
|
128
|
+
'https://example.com/icon-192.png': {
|
|
129
|
+
status: 200,
|
|
130
|
+
contentType: 'image/png',
|
|
131
|
+
readableStream: yield (0, helper_1.filePathToReadableStream)(testIcon192)
|
|
132
|
+
},
|
|
133
|
+
'https://example.com/icon-512.png': {
|
|
134
|
+
status: 200,
|
|
135
|
+
contentType: 'image/png',
|
|
136
|
+
readableStream: yield (0, helper_1.filePathToReadableStream)(testIcon512)
|
|
137
|
+
}
|
|
138
|
+
}));
|
|
139
|
+
const expectedIconReport = [
|
|
140
|
+
{
|
|
141
|
+
status: types_1.CheckerStatus.Ok,
|
|
142
|
+
id: types_1.MessageId.manifestIconDeclared,
|
|
143
|
+
}, {
|
|
144
|
+
status: types_1.CheckerStatus.Ok,
|
|
145
|
+
id: types_1.MessageId.manifestIconDownloadable,
|
|
146
|
+
}, {
|
|
147
|
+
status: types_1.CheckerStatus.Ok,
|
|
148
|
+
id: types_1.MessageId.manifestIconRightSize,
|
|
149
|
+
}
|
|
150
|
+
];
|
|
151
|
+
expect(filterOutput(report)).toEqual({
|
|
152
|
+
messages: [{
|
|
153
|
+
status: types_1.CheckerStatus.Ok,
|
|
154
|
+
id: types_1.MessageId.manifestName,
|
|
155
|
+
}, {
|
|
156
|
+
status: types_1.CheckerStatus.Ok,
|
|
157
|
+
id: types_1.MessageId.manifestShortName,
|
|
158
|
+
}, {
|
|
159
|
+
status: types_1.CheckerStatus.Ok,
|
|
160
|
+
id: types_1.MessageId.manifestBackgroundColor,
|
|
161
|
+
}, {
|
|
162
|
+
status: types_1.CheckerStatus.Ok,
|
|
163
|
+
id: types_1.MessageId.manifestThemeColor,
|
|
164
|
+
},
|
|
165
|
+
...expectedIconReport, ...expectedIconReport], // Two icons
|
|
166
|
+
name: 'My long name',
|
|
167
|
+
shortName: 'Short!',
|
|
168
|
+
backgroundColor: '#123456',
|
|
169
|
+
themeColor: '#abcdef',
|
|
170
|
+
icon: (0, helper_1.bufferToDataUrl)(yield (0, helper_1.readableStreamToBuffer)(yield (0, helper_1.filePathToReadableStream)(testIcon512)), 'image/png')
|
|
171
|
+
});
|
|
172
|
+
}));
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@realfavicongenerator/check-favicon",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Check the favicon of a website",
|
|
5
|
-
"main": "index.
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
6
7
|
"scripts": {
|
|
7
|
-
"test": "jest"
|
|
8
|
+
"test": "jest",
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"prepublishOnly": "npm run build"
|
|
8
11
|
},
|
|
9
12
|
"repository": {
|
|
10
13
|
"type": "git",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parse } from 'node-html-parser'
|
|
2
2
|
import { checkSvgFavicon } from "./desktop";
|
|
3
|
-
import { CheckerMessage, CheckerStatus, FetchResponse, MessageId } from '
|
|
3
|
+
import { CheckerMessage, CheckerStatus, FetchResponse, MessageId } from '../types';
|
|
4
4
|
import { filePathToReadableStream, filePathToString, stringToReadableStream } from '../helper';
|
|
5
5
|
import { testFetcher } from '../test-helper';
|
|
6
6
|
|
package/src/desktop/desktop.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { CheckerMessage, CheckerStatus, DesktopFaviconReport, Fetcher, MessageId
|
|
1
|
+
import { CheckerMessage, CheckerStatus, DesktopFaviconReport, Fetcher, MessageId } from "../types";
|
|
2
2
|
import { HTMLElement } from 'node-html-parser'
|
|
3
3
|
import sharp from 'sharp'
|
|
4
|
-
import { CheckIconProcessor, checkIcon, mergeUrlAndPath, readableStreamToString } from "../helper";
|
|
4
|
+
import { CheckIconProcessor, checkIcon, fetchFetcher, mergeUrlAndPath, readableStreamToString } from "../helper";
|
|
5
5
|
import { checkIcoFavicon } from "./ico";
|
|
6
6
|
|
|
7
7
|
export const PngFaviconFileSize = 48;
|
package/src/desktop/ico.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CheckerMessage, CheckerStatus, Fetcher, MessageId } from "
|
|
1
|
+
import { CheckerMessage, CheckerStatus, Fetcher, MessageId } from "../types";
|
|
2
2
|
import { HTMLElement } from 'node-html-parser'
|
|
3
3
|
import { mergeUrlAndPath, readableStreamToBuffer } from "../helper";
|
|
4
4
|
import decodeIco from "decode-ico";
|
package/src/helper.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'fs/promises'
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { Fetcher
|
|
3
|
+
import { Fetcher } from './types';
|
|
4
4
|
import sharp, { FormatEnum } from 'sharp';
|
|
5
5
|
|
|
6
6
|
export const filePathToReadableStream = async (path: string): Promise<ReadableStream> => {
|
|
@@ -83,6 +83,23 @@ export type CheckIconProcessor = {
|
|
|
83
83
|
wrongSize: (widthHeight: number) => void
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
export const pathToMimeType = (path: string): string => {
|
|
87
|
+
const ext = path.split('.').pop();
|
|
88
|
+
switch (ext) {
|
|
89
|
+
case 'png':
|
|
90
|
+
return 'image/png';
|
|
91
|
+
case 'svg':
|
|
92
|
+
return 'image/svg+xml';
|
|
93
|
+
case 'ico':
|
|
94
|
+
return 'image/x-icon';
|
|
95
|
+
case 'jpg':
|
|
96
|
+
case 'jpeg':
|
|
97
|
+
return 'image/jpeg';
|
|
98
|
+
default:
|
|
99
|
+
return 'application/octet-stream';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
86
103
|
export const checkIcon = async (
|
|
87
104
|
iconUrl: string | undefined,
|
|
88
105
|
processor: CheckIconProcessor,
|
|
@@ -168,3 +185,18 @@ export const parseSizesAttribute = (sizes: string | undefined | null): number |
|
|
|
168
185
|
export const bufferToDataUrl = (buffer: Buffer, mimeType: string): string => {
|
|
169
186
|
return `data:${mimeType};base64,${buffer.toString('base64')}`;
|
|
170
187
|
}
|
|
188
|
+
|
|
189
|
+
export const fetchFetcher: Fetcher = async (url, contentType) => {
|
|
190
|
+
const res = await fetch(url, {
|
|
191
|
+
headers: {
|
|
192
|
+
'Content-Type': contentType || pathToMimeType(url),
|
|
193
|
+
'user-agent': 'RealFaviconGenerator Favicon Checker'
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
status: res.status,
|
|
199
|
+
contentType: res.headers.get('Content-Type') || null,
|
|
200
|
+
readableStream: res.body
|
|
201
|
+
}
|
|
202
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,161 +1,16 @@
|
|
|
1
1
|
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
svgFaviconDownloadable,
|
|
18
|
-
svgFaviconSquare,
|
|
19
|
-
svgFaviconNotSquare,
|
|
20
|
-
|
|
21
|
-
noIcoFavicon,
|
|
22
|
-
multipleIcoFavicons,
|
|
23
|
-
icoFaviconDeclared,
|
|
24
|
-
noIcoFaviconHref,
|
|
25
|
-
icoFavicon404,
|
|
26
|
-
icoFaviconCannotGet,
|
|
27
|
-
icoFaviconDownloadable,
|
|
28
|
-
icoFaviconExtraSizes,
|
|
29
|
-
icoFaviconMissingSizes,
|
|
30
|
-
icoFaviconExpectedSizes,
|
|
31
|
-
|
|
32
|
-
noDesktopPngFavicon,
|
|
33
|
-
no48x48DesktopPngFavicon,
|
|
34
|
-
desktopPngFaviconDeclared,
|
|
35
|
-
noDesktopPngFaviconHref,
|
|
36
|
-
desktopPngFaviconCannotGet,
|
|
37
|
-
desktopPngFaviconDownloadable,
|
|
38
|
-
desktopPngFavicon404,
|
|
39
|
-
desktopPngFaviconWrongSize,
|
|
40
|
-
desktopPngFaviconRightSize,
|
|
41
|
-
|
|
42
|
-
noTouchWebAppTitle,
|
|
43
|
-
multipleTouchWebAppTitles,
|
|
44
|
-
emptyTouchWebAppTitle,
|
|
45
|
-
touchWebAppTitleDeclared,
|
|
46
|
-
noTouchIcon,
|
|
47
|
-
duplicatedTouchIconSizes,
|
|
48
|
-
touchIconWithSize,
|
|
49
|
-
touchIconDeclared,
|
|
50
|
-
noTouchIconHref,
|
|
51
|
-
touchIcon404,
|
|
52
|
-
touchIconCannotGet,
|
|
53
|
-
touchIconDownloadable,
|
|
54
|
-
touchIconSquare,
|
|
55
|
-
touchIcon180x180,
|
|
56
|
-
touchIconNotSquare,
|
|
57
|
-
touchIconWrongSize,
|
|
58
|
-
|
|
59
|
-
noManifest,
|
|
60
|
-
noManifestHref,
|
|
61
|
-
manifest404,
|
|
62
|
-
manifestCannotGet,
|
|
63
|
-
manifestInvalidJson,
|
|
64
|
-
manifestName,
|
|
65
|
-
noManifestName,
|
|
66
|
-
manifestShortName,
|
|
67
|
-
noManifestShortName,
|
|
68
|
-
manifestBackgroundColor,
|
|
69
|
-
noManifestBackgroundColor,
|
|
70
|
-
manifestThemeColor,
|
|
71
|
-
noManifestThemeColor,
|
|
72
|
-
noManifestIcons,
|
|
73
|
-
noManifestIcon,
|
|
74
|
-
manifestIconDeclared,
|
|
75
|
-
manifestIconCannotGet,
|
|
76
|
-
manifestIconDownloadable,
|
|
77
|
-
manifestIcon404,
|
|
78
|
-
manifestIconNoHref,
|
|
79
|
-
manifestIconNotSquare,
|
|
80
|
-
manifestIconRightSize,
|
|
81
|
-
manifestIconSquare,
|
|
82
|
-
manifestIconWrongSize
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export type CheckerMessage = {
|
|
86
|
-
status: CheckerStatus,
|
|
87
|
-
id: MessageId,
|
|
88
|
-
text: string
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export type FetchResponse = {
|
|
92
|
-
status: number,
|
|
93
|
-
contentType: string | null,
|
|
94
|
-
readableStream?: ReadableStream | null
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export type Fetcher = (url: string, contentType?: string) => Promise<FetchResponse>;
|
|
98
|
-
|
|
99
|
-
export const fetchFetcher: Fetcher = async (url, contentType) => {
|
|
100
|
-
const res = await fetch(url, {
|
|
101
|
-
headers: {
|
|
102
|
-
'Content-Type': contentType || pathToMimeType(url),
|
|
103
|
-
'user-agent': 'RealFaviconGenerator Favicon Checker'
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
status: res.status,
|
|
109
|
-
contentType: res.headers.get('Content-Type') || null,
|
|
110
|
-
readableStream: res.body
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export type DesktopFaviconReport = {
|
|
115
|
-
messages: CheckerMessage[],
|
|
116
|
-
icon: string | null,
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export type TouchIconTitleReport = {
|
|
120
|
-
messages: CheckerMessage[],
|
|
121
|
-
appTitle?: string
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export type TouchIconIconReport = {
|
|
125
|
-
messages: CheckerMessage[],
|
|
126
|
-
touchIcon: string | null,
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export type WebManifestReport = {
|
|
130
|
-
messages: CheckerMessage[],
|
|
131
|
-
name?: string,
|
|
132
|
-
shortName?: string,
|
|
133
|
-
backgroundColor?: string,
|
|
134
|
-
themeColor?: string,
|
|
135
|
-
icon: string | null
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export type FaviconReport = {
|
|
139
|
-
desktop: DesktopFaviconReport,
|
|
140
|
-
touchIcon: TouchIconReport,
|
|
141
|
-
webAppManifest: WebManifestReport
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export type TouchIconReport = TouchIconIconReport & TouchIconTitleReport;
|
|
145
|
-
|
|
146
|
-
export const pathToMimeType = (path: string): string => {
|
|
147
|
-
const ext = path.split('.').pop();
|
|
148
|
-
switch (ext) {
|
|
149
|
-
case 'png':
|
|
150
|
-
return 'image/png';
|
|
151
|
-
case 'svg':
|
|
152
|
-
return 'image/svg+xml';
|
|
153
|
-
case 'ico':
|
|
154
|
-
return 'image/x-icon';
|
|
155
|
-
case 'jpg':
|
|
156
|
-
case 'jpeg':
|
|
157
|
-
return 'image/jpeg';
|
|
158
|
-
default:
|
|
159
|
-
return 'application/octet-stream';
|
|
160
|
-
}
|
|
161
|
-
}
|
|
2
|
+
export {
|
|
3
|
+
CheckerStatus,
|
|
4
|
+
MessageId,
|
|
5
|
+
CheckerMessage,
|
|
6
|
+
DesktopFaviconReport,
|
|
7
|
+
TouchIconTitleReport,
|
|
8
|
+
TouchIconIconReport,
|
|
9
|
+
WebManifestReport,
|
|
10
|
+
FaviconReport,
|
|
11
|
+
TouchIconReport
|
|
12
|
+
} from './types';
|
|
13
|
+
|
|
14
|
+
export { checkDesktopFavicon, checkSvgFavicon } from "./desktop/desktop"
|
|
15
|
+
export { checkTouchIcon } from "./touch-icon"
|
|
16
|
+
export { checkWebManifest } from "./web-manifest"
|
package/src/test-helper.ts
CHANGED
package/src/touch-icon.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parse } from 'node-html-parser'
|
|
2
|
-
import { CheckerMessage, CheckerStatus, FetchResponse, MessageId } from "
|
|
2
|
+
import { CheckerMessage, CheckerStatus, FetchResponse, MessageId } from "./types";
|
|
3
3
|
import { checkTouchIcon, checkTouchIconIcon, checkTouchIconTitle, getDuplicatedSizes } from "./touch-icon";
|
|
4
4
|
import { testFetcher } from './test-helper';
|
|
5
5
|
import { bufferToDataUrl, filePathToReadableStream, readableStreamToBuffer } from './helper';
|
package/src/touch-icon.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CheckerMessage, CheckerStatus, Fetcher, MessageId, TouchIconIconReport, TouchIconReport, TouchIconTitleReport
|
|
1
|
+
import { CheckerMessage, CheckerStatus, Fetcher, MessageId, TouchIconIconReport, TouchIconReport, TouchIconTitleReport } from "./types";
|
|
2
2
|
import { HTMLElement } from 'node-html-parser'
|
|
3
|
-
import { CheckIconProcessor, checkIcon, mergeUrlAndPath } from "./helper";
|
|
3
|
+
import { CheckIconProcessor, checkIcon, fetchFetcher, mergeUrlAndPath } from "./helper";
|
|
4
4
|
|
|
5
5
|
export const checkTouchIconTitle = async (baseUrl: string, head: HTMLElement | null, fetcher: Fetcher = fetchFetcher): Promise<TouchIconTitleReport> => {
|
|
6
6
|
const messages: CheckerMessage[] = [];
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
|
|
2
|
+
export enum CheckerStatus {
|
|
3
|
+
Ok = 'Ok',
|
|
4
|
+
Error = 'Error',
|
|
5
|
+
Warning = 'Warning'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export enum MessageId {
|
|
9
|
+
noHead,
|
|
10
|
+
|
|
11
|
+
svgFaviconDeclared,
|
|
12
|
+
noSvgFavicon,
|
|
13
|
+
multipleSvgFavicons,
|
|
14
|
+
noSvgFaviconHref,
|
|
15
|
+
svgFavicon404,
|
|
16
|
+
svgFaviconCannotGet,
|
|
17
|
+
svgFaviconDownloadable,
|
|
18
|
+
svgFaviconSquare,
|
|
19
|
+
svgFaviconNotSquare,
|
|
20
|
+
|
|
21
|
+
noIcoFavicon,
|
|
22
|
+
multipleIcoFavicons,
|
|
23
|
+
icoFaviconDeclared,
|
|
24
|
+
noIcoFaviconHref,
|
|
25
|
+
icoFavicon404,
|
|
26
|
+
icoFaviconCannotGet,
|
|
27
|
+
icoFaviconDownloadable,
|
|
28
|
+
icoFaviconExtraSizes,
|
|
29
|
+
icoFaviconMissingSizes,
|
|
30
|
+
icoFaviconExpectedSizes,
|
|
31
|
+
|
|
32
|
+
noDesktopPngFavicon,
|
|
33
|
+
no48x48DesktopPngFavicon,
|
|
34
|
+
desktopPngFaviconDeclared,
|
|
35
|
+
noDesktopPngFaviconHref,
|
|
36
|
+
desktopPngFaviconCannotGet,
|
|
37
|
+
desktopPngFaviconDownloadable,
|
|
38
|
+
desktopPngFavicon404,
|
|
39
|
+
desktopPngFaviconWrongSize,
|
|
40
|
+
desktopPngFaviconRightSize,
|
|
41
|
+
|
|
42
|
+
noTouchWebAppTitle,
|
|
43
|
+
multipleTouchWebAppTitles,
|
|
44
|
+
emptyTouchWebAppTitle,
|
|
45
|
+
touchWebAppTitleDeclared,
|
|
46
|
+
noTouchIcon,
|
|
47
|
+
duplicatedTouchIconSizes,
|
|
48
|
+
touchIconWithSize,
|
|
49
|
+
touchIconDeclared,
|
|
50
|
+
noTouchIconHref,
|
|
51
|
+
touchIcon404,
|
|
52
|
+
touchIconCannotGet,
|
|
53
|
+
touchIconDownloadable,
|
|
54
|
+
touchIconSquare,
|
|
55
|
+
touchIcon180x180,
|
|
56
|
+
touchIconNotSquare,
|
|
57
|
+
touchIconWrongSize,
|
|
58
|
+
|
|
59
|
+
noManifest,
|
|
60
|
+
noManifestHref,
|
|
61
|
+
manifest404,
|
|
62
|
+
manifestCannotGet,
|
|
63
|
+
manifestInvalidJson,
|
|
64
|
+
manifestName,
|
|
65
|
+
noManifestName,
|
|
66
|
+
manifestShortName,
|
|
67
|
+
noManifestShortName,
|
|
68
|
+
manifestBackgroundColor,
|
|
69
|
+
noManifestBackgroundColor,
|
|
70
|
+
manifestThemeColor,
|
|
71
|
+
noManifestThemeColor,
|
|
72
|
+
noManifestIcons,
|
|
73
|
+
noManifestIcon,
|
|
74
|
+
manifestIconDeclared,
|
|
75
|
+
manifestIconCannotGet,
|
|
76
|
+
manifestIconDownloadable,
|
|
77
|
+
manifestIcon404,
|
|
78
|
+
manifestIconNoHref,
|
|
79
|
+
manifestIconNotSquare,
|
|
80
|
+
manifestIconRightSize,
|
|
81
|
+
manifestIconSquare,
|
|
82
|
+
manifestIconWrongSize
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type CheckerMessage = {
|
|
86
|
+
status: CheckerStatus,
|
|
87
|
+
id: MessageId,
|
|
88
|
+
text: string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type FetchResponse = {
|
|
92
|
+
status: number,
|
|
93
|
+
contentType: string | null,
|
|
94
|
+
readableStream?: ReadableStream | null
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export type Fetcher = (url: string, contentType?: string) => Promise<FetchResponse>;
|
|
98
|
+
|
|
99
|
+
export type DesktopFaviconReport = {
|
|
100
|
+
messages: CheckerMessage[],
|
|
101
|
+
icon: string | null,
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export type TouchIconTitleReport = {
|
|
105
|
+
messages: CheckerMessage[],
|
|
106
|
+
appTitle?: string
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export type TouchIconIconReport = {
|
|
110
|
+
messages: CheckerMessage[],
|
|
111
|
+
touchIcon: string | null,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export type WebManifestReport = {
|
|
115
|
+
messages: CheckerMessage[],
|
|
116
|
+
name?: string,
|
|
117
|
+
shortName?: string,
|
|
118
|
+
backgroundColor?: string,
|
|
119
|
+
themeColor?: string,
|
|
120
|
+
icon: string | null
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export type FaviconReport = {
|
|
124
|
+
desktop: DesktopFaviconReport,
|
|
125
|
+
touchIcon: TouchIconReport,
|
|
126
|
+
webAppManifest: WebManifestReport
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export type TouchIconReport = TouchIconIconReport & TouchIconTitleReport;
|
package/src/web-manifest.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import parse from "node-html-parser";
|
|
2
|
-
import { CheckerMessage, CheckerStatus, FetchResponse, MessageId, WebManifestReport } from "
|
|
2
|
+
import { CheckerMessage, CheckerStatus, FetchResponse, MessageId, WebManifestReport } from "./types";
|
|
3
3
|
import { checkWebManifest, checkWebManifestFile } from "./web-manifest";
|
|
4
4
|
import { testFetcher } from "./test-helper";
|
|
5
5
|
import { bufferToDataUrl, filePathToReadableStream, readableStreamToBuffer } from "./helper";
|
package/src/web-manifest.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HTMLElement } from "node-html-parser";
|
|
2
|
-
import { CheckerMessage, CheckerStatus, Fetcher, MessageId, WebManifestReport
|
|
3
|
-
import { CheckIconProcessor, checkIcon, mergeUrlAndPath } from "./helper";
|
|
2
|
+
import { CheckerMessage, CheckerStatus, Fetcher, MessageId, WebManifestReport } from "./types";
|
|
3
|
+
import { CheckIconProcessor, checkIcon, fetchFetcher, mergeUrlAndPath, pathToMimeType } from "./helper";
|
|
4
4
|
|
|
5
5
|
export const checkWebManifest = async (baseUrl: string, head: HTMLElement | null, fetcher: Fetcher = fetchFetcher): Promise<WebManifestReport> => {
|
|
6
6
|
const messages: CheckerMessage[] = [];
|
package/tsconfig.json
CHANGED
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
|
50
50
|
|
|
51
51
|
/* Emit */
|
|
52
|
-
|
|
52
|
+
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
|
53
53
|
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
|
54
54
|
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
|
55
55
|
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
|
56
56
|
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
|
57
57
|
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
|
58
|
-
|
|
58
|
+
"outDir": "./dist", /* Specify an output folder for all emitted files. */
|
|
59
59
|
// "removeComments": true, /* Disable emitting comments. */
|
|
60
60
|
// "noEmit": true, /* Disable emitting files from a compilation. */
|
|
61
61
|
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|