@degreesign/webapp 1.6.8
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/LICENSE +21 -0
- package/README.md +189 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +10 -0
- package/dist/src/main.d.ts +4 -0
- package/dist/src/main.js +129 -0
- package/dist/src/obfuscate.d.ts +2 -0
- package/dist/src/obfuscate.js +35 -0
- package/dist/src/sw.d.ts +7 -0
- package/dist/src/sw.js +173 -0
- package/dist/src/sw_register.d.ts +0 -0
- package/dist/src/sw_register.js +10 -0
- package/dist/src/types.d.ts +262 -0
- package/dist/src/types.js +2 -0
- package/dist/src/utils.d.ts +18 -0
- package/dist/src/utils.js +276 -0
- package/dist/src/web.d.ts +2 -0
- package/dist/src/web.js +317 -0
- package/package.json +55 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { ResolveOptions } from "webpack";
|
|
2
|
+
import { Configuration, ModuleOptions } from "webpack";
|
|
3
|
+
import CssMinimizerPlugin from "css-minimizer-webpack-plugin";
|
|
4
|
+
export interface StringObj {
|
|
5
|
+
[key: string]: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Page {
|
|
8
|
+
/** URI of the page */
|
|
9
|
+
uri: string;
|
|
10
|
+
/** Name of the page */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Short name of the page (optional) */
|
|
13
|
+
short_name?: string;
|
|
14
|
+
/** Description of the page */
|
|
15
|
+
description: string;
|
|
16
|
+
/** Icon associated with the page (optional) */
|
|
17
|
+
icon?: string;
|
|
18
|
+
/**
|
|
19
|
+
* [Maskable] Icon associated with the page (optional)
|
|
20
|
+
*
|
|
21
|
+
* maskable icon should be centered in safe zone (inner 338x338 pixels of 512x512)
|
|
22
|
+
* prevents masking from cropping important elements
|
|
23
|
+
*/
|
|
24
|
+
iconMaskable?: string;
|
|
25
|
+
/** Flag to indicate if the page is a shortcut (optional) */
|
|
26
|
+
shortcut?: boolean;
|
|
27
|
+
/** Flag to indicate if the page should be excluded from indexing (optional) */
|
|
28
|
+
noindex?: boolean;
|
|
29
|
+
/** Publication date of the page (optional) */
|
|
30
|
+
publishDate?: string;
|
|
31
|
+
/** URL or path to the cover image for the page (optional) */
|
|
32
|
+
coverImage?: string;
|
|
33
|
+
/** Description of the cover image (optional) */
|
|
34
|
+
coverImageDescription?: string;
|
|
35
|
+
/** Custom header HTML (optional) */
|
|
36
|
+
headerHTML?: string;
|
|
37
|
+
/** Custom menu HTML (optional) */
|
|
38
|
+
menuHTML?: string;
|
|
39
|
+
/** Custom footer HTML (optional) */
|
|
40
|
+
footerHTML?: string;
|
|
41
|
+
/** Custom body HTML Elements (optional) */
|
|
42
|
+
customHTML?: string[];
|
|
43
|
+
/** Page code has PHP */
|
|
44
|
+
isPHP?: boolean;
|
|
45
|
+
/** Page keywords comma separated (optional) */
|
|
46
|
+
keywords?: string;
|
|
47
|
+
/** Custom Canonical URL */
|
|
48
|
+
canonicalURL?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface ConfigBase {
|
|
51
|
+
/** Source directory path */
|
|
52
|
+
srcDir: string;
|
|
53
|
+
/** Production directory path */
|
|
54
|
+
productionDir: string;
|
|
55
|
+
/** Application mode, either development or production */
|
|
56
|
+
mode?: 'development' | 'production';
|
|
57
|
+
/** Flag to enable or disable obfuscation */
|
|
58
|
+
obfuscateON?: boolean;
|
|
59
|
+
/** Flag to enable or disable JS code minimisation */
|
|
60
|
+
minimiseON?: boolean;
|
|
61
|
+
/** Port Number */
|
|
62
|
+
port?: number;
|
|
63
|
+
/** File Size (MB) */
|
|
64
|
+
maxFileSizeMB?: number;
|
|
65
|
+
/** Resolve Options */
|
|
66
|
+
resolveOptions?: ResolveOptions;
|
|
67
|
+
/** License Text */
|
|
68
|
+
licenseText?: string;
|
|
69
|
+
/** Show Packages Analyser Window */
|
|
70
|
+
openAnalyzer?: boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface ConfigWebApp extends ConfigBase {
|
|
73
|
+
/** Name of the website */
|
|
74
|
+
websiteName: string;
|
|
75
|
+
/** Domain of the website */
|
|
76
|
+
websiteDomain: string;
|
|
77
|
+
/** Short name of the application */
|
|
78
|
+
appShortName: string;
|
|
79
|
+
/** Twitter username associated with the application */
|
|
80
|
+
twitterUserName: string;
|
|
81
|
+
/** Publication time of the website */
|
|
82
|
+
publishedTime: string;
|
|
83
|
+
/** Author of the website */
|
|
84
|
+
author: string;
|
|
85
|
+
/** Title of the website */
|
|
86
|
+
websiteTitle: string;
|
|
87
|
+
/** Description of the website */
|
|
88
|
+
websiteDescription: string;
|
|
89
|
+
/** URL or path to the cover image */
|
|
90
|
+
coverImage: string;
|
|
91
|
+
/** Description of the cover image */
|
|
92
|
+
coverImageDescription: string;
|
|
93
|
+
/** Background color for the application */
|
|
94
|
+
background_color: string;
|
|
95
|
+
/** Theme color for the application */
|
|
96
|
+
theme_color: string;
|
|
97
|
+
/** Path to the application icon */
|
|
98
|
+
appIcon: string;
|
|
99
|
+
/**
|
|
100
|
+
* Path to the application icon (maskable)
|
|
101
|
+
*
|
|
102
|
+
* maskable icon should be centered in safe zone (inner 338x338 pixels of 512x512)
|
|
103
|
+
* prevents masking from cropping important elements
|
|
104
|
+
*/
|
|
105
|
+
appIconMaskable: string;
|
|
106
|
+
/** favicon file name or path */
|
|
107
|
+
fav_icon: string;
|
|
108
|
+
/** Orientation of the application, either portrait or landscape */
|
|
109
|
+
orientation: 'portrait' | 'landscape';
|
|
110
|
+
/** Pages list array */
|
|
111
|
+
pagesList: Page[];
|
|
112
|
+
/** Array of common HTML elements to include */
|
|
113
|
+
htmlCommonElements?: (`header` | `footer` | `menu`)[];
|
|
114
|
+
/** Assets directory path */
|
|
115
|
+
assetsDir: string;
|
|
116
|
+
/** Common directory path */
|
|
117
|
+
commonDir: string;
|
|
118
|
+
/** Images directory path */
|
|
119
|
+
imagesDir: string;
|
|
120
|
+
/** Pages directory path */
|
|
121
|
+
pagesDir: string;
|
|
122
|
+
/** Home page identifier or path */
|
|
123
|
+
pageHome: string;
|
|
124
|
+
/** Added to end of htaccess */
|
|
125
|
+
htaccessCustom: string;
|
|
126
|
+
/** App start URI */
|
|
127
|
+
startURI?: string;
|
|
128
|
+
/** App Language */
|
|
129
|
+
language?: string;
|
|
130
|
+
/** css Discard Unused */
|
|
131
|
+
cssDiscardUnused?: boolean;
|
|
132
|
+
/** Update service worker */
|
|
133
|
+
updateServiceWorker?: boolean;
|
|
134
|
+
/** Online reference file */
|
|
135
|
+
onlineIndicatorFile?: string;
|
|
136
|
+
}
|
|
137
|
+
export interface ConfigServer extends ConfigBase {
|
|
138
|
+
/** Server Files list */
|
|
139
|
+
filesList: string[];
|
|
140
|
+
}
|
|
141
|
+
export type ConfigBuild = {
|
|
142
|
+
type: `webapp`;
|
|
143
|
+
} & ConfigWebApp | {
|
|
144
|
+
type: `server`;
|
|
145
|
+
} & ConfigServer;
|
|
146
|
+
/** Update Times */
|
|
147
|
+
export interface UpdateTimes {
|
|
148
|
+
/** service worker */
|
|
149
|
+
serviceWorker?: number;
|
|
150
|
+
}
|
|
151
|
+
interface Icon {
|
|
152
|
+
/** Source URL or path to the icon */
|
|
153
|
+
src: string;
|
|
154
|
+
/** MIME type of the icon */
|
|
155
|
+
type: string;
|
|
156
|
+
/** Dimensions of the icon (e.g., '192x192') */
|
|
157
|
+
sizes: string;
|
|
158
|
+
/** Purpose of the icon, either maskable or any */
|
|
159
|
+
purpose: 'maskable' | 'any';
|
|
160
|
+
}
|
|
161
|
+
interface Shortcut {
|
|
162
|
+
/** Name of the shortcut */
|
|
163
|
+
name: string;
|
|
164
|
+
/** Short name of the shortcut */
|
|
165
|
+
short_name: string;
|
|
166
|
+
/** Description of the shortcut */
|
|
167
|
+
description: string;
|
|
168
|
+
/** URL the shortcut points to */
|
|
169
|
+
url: string;
|
|
170
|
+
/** Array of icons associated with the shortcut */
|
|
171
|
+
icons: Icon[];
|
|
172
|
+
}
|
|
173
|
+
export interface WebManifest {
|
|
174
|
+
/** Background color for the application */
|
|
175
|
+
background_color: string;
|
|
176
|
+
/** Theme color for the application */
|
|
177
|
+
theme_color: string;
|
|
178
|
+
/** Array of icons for the application */
|
|
179
|
+
icons: Icon[];
|
|
180
|
+
/** Array of shortcuts for the application */
|
|
181
|
+
shortcuts: Shortcut[];
|
|
182
|
+
/** Display mode for the application (e.g., 'standalone', 'fullscreen') */
|
|
183
|
+
display: string;
|
|
184
|
+
/** Orientation of the application, either portrait or landscape */
|
|
185
|
+
orientation: 'portrait' | 'landscape';
|
|
186
|
+
/** Short name of the application */
|
|
187
|
+
short_name: string;
|
|
188
|
+
/** Starting URL of the application */
|
|
189
|
+
start_url: string;
|
|
190
|
+
/** Description of the application */
|
|
191
|
+
description: string;
|
|
192
|
+
/** Full name of the application */
|
|
193
|
+
name: string;
|
|
194
|
+
}
|
|
195
|
+
type MetaTag = string | false | {
|
|
196
|
+
[attributeName: string]: string | boolean;
|
|
197
|
+
};
|
|
198
|
+
export interface MetaTags {
|
|
199
|
+
/** Dictionary of meta tags, where the key is the tag name and value is the tag content or attributes */
|
|
200
|
+
[key: string]: MetaTag;
|
|
201
|
+
}
|
|
202
|
+
export interface MetaTagsInput {
|
|
203
|
+
/** Author of the website */
|
|
204
|
+
author: string;
|
|
205
|
+
/** Description of the website */
|
|
206
|
+
websiteDescription: string;
|
|
207
|
+
/** Name of the website */
|
|
208
|
+
websiteName: string;
|
|
209
|
+
/** Title of the website */
|
|
210
|
+
websiteTitle: string;
|
|
211
|
+
/** URL or path to the cover image */
|
|
212
|
+
coverImageLink: string;
|
|
213
|
+
/** Description of the cover image */
|
|
214
|
+
coverImageDescription: string;
|
|
215
|
+
/** Publication time of the website */
|
|
216
|
+
publishedTime: string;
|
|
217
|
+
/** URL of the website */
|
|
218
|
+
websiteLink: string;
|
|
219
|
+
/** Data string for additional metadata */
|
|
220
|
+
dataString: string;
|
|
221
|
+
/** Theme color for the website */
|
|
222
|
+
theme_color: string;
|
|
223
|
+
/** Twitter username associated with the website */
|
|
224
|
+
twitterUserName: string;
|
|
225
|
+
/** Path to the application icon file */
|
|
226
|
+
appIconFile: string;
|
|
227
|
+
/** Flag to indicate if the page should be excluded from indexing (optional) */
|
|
228
|
+
noindex?: boolean;
|
|
229
|
+
/** Language of the website */
|
|
230
|
+
language: string;
|
|
231
|
+
/** check if home */
|
|
232
|
+
isHome: boolean;
|
|
233
|
+
/** Keywords (optional) */
|
|
234
|
+
keywords?: string;
|
|
235
|
+
}
|
|
236
|
+
export interface TemplateHTMLOptions {
|
|
237
|
+
/** HTML for link tags (optional) */
|
|
238
|
+
links?: string;
|
|
239
|
+
/** HTML for the header section (optional) */
|
|
240
|
+
headerHTML?: string;
|
|
241
|
+
/** Title of the page (optional) */
|
|
242
|
+
title?: string;
|
|
243
|
+
/** HTML for the menu section (optional) */
|
|
244
|
+
menuHTML?: string;
|
|
245
|
+
/** Custom HTML content (optional) */
|
|
246
|
+
bodyHTML?: string;
|
|
247
|
+
/** HTML for the page body (optional) */
|
|
248
|
+
pageBody?: string;
|
|
249
|
+
/** HTML for the footer section (optional) */
|
|
250
|
+
footerHTML?: string;
|
|
251
|
+
}
|
|
252
|
+
export interface HtmlContent {
|
|
253
|
+
id: string;
|
|
254
|
+
content: string;
|
|
255
|
+
}
|
|
256
|
+
export interface WebConfig {
|
|
257
|
+
entryPoints: StringObj;
|
|
258
|
+
customWebRules: ModuleOptions["rules"];
|
|
259
|
+
configWebPlugins: Configuration["plugins"];
|
|
260
|
+
cssMinimise: CssMinimizerPlugin<CssMinimizerPlugin.CssNanoOptionsExtended>[];
|
|
261
|
+
}
|
|
262
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MetaTags, MetaTagsInput } from "./types";
|
|
2
|
+
declare const
|
|
3
|
+
/** Write to files */
|
|
4
|
+
writeData: (file: string, code: string) => boolean,
|
|
5
|
+
/** Write JSON files */
|
|
6
|
+
writeJSON: (file: string, code: any) => boolean,
|
|
7
|
+
/** Read files */
|
|
8
|
+
readData: (file: string, internal?: boolean) => string,
|
|
9
|
+
/** Read JSON files */
|
|
10
|
+
readJSON: (file: string, internal?: boolean) => any, metaTags: ({ author, websiteDescription, websiteName, websiteTitle, coverImageLink, coverImageDescription, publishedTime, websiteLink, dataString, theme_color, twitterUserName, appIconFile, noindex, language, isHome, keywords, }: MetaTagsInput) => MetaTags, linkTags: ({ favIconFile, timeNow, coverImageLink, canonicalURL, }: {
|
|
11
|
+
coverImageLink: string;
|
|
12
|
+
favIconFile: string;
|
|
13
|
+
timeNow: number;
|
|
14
|
+
canonicalURL: string;
|
|
15
|
+
}) => string,
|
|
16
|
+
/** Check for PHP tag */
|
|
17
|
+
isPHPTag: (code: string) => boolean;
|
|
18
|
+
export { writeData, writeJSON, readData, readJSON, metaTags, linkTags, isPHPTag, };
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isPHPTag = exports.linkTags = exports.metaTags = exports.readJSON = exports.readData = exports.writeJSON = exports.writeData = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const
|
|
10
|
+
/** Write to files */
|
|
11
|
+
writeData = (file, code) => {
|
|
12
|
+
try {
|
|
13
|
+
return code ? (fs_1.default.writeFileSync(path_1.default.resolve(process.cwd(), file), code, `utf8`),
|
|
14
|
+
true) : (console.log(`no data to write to`, file),
|
|
15
|
+
false);
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
console.log(`failed to write data to`, file);
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
;
|
|
22
|
+
},
|
|
23
|
+
/** Write JSON files */
|
|
24
|
+
writeJSON = (file, code) => {
|
|
25
|
+
try {
|
|
26
|
+
if (!code) {
|
|
27
|
+
console.log(`no JSON data to write to`, file);
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
;
|
|
31
|
+
const data = JSON.stringify(code);
|
|
32
|
+
writeData(file, data);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
console.log(`failed to write JSON at`, file);
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
;
|
|
40
|
+
},
|
|
41
|
+
/** Read files */
|
|
42
|
+
readData = (file, internal) => {
|
|
43
|
+
try {
|
|
44
|
+
const filePath = internal ? path_1.default.join(__dirname, file)
|
|
45
|
+
: path_1.default.resolve(process.cwd(), file), data = fs_1.default.readFileSync(filePath, `utf8`);
|
|
46
|
+
if (!data) {
|
|
47
|
+
console.log(`no data to read at path`, filePath);
|
|
48
|
+
return ``;
|
|
49
|
+
}
|
|
50
|
+
;
|
|
51
|
+
return data;
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
console.log(`failed to read data at`, file);
|
|
55
|
+
return ``;
|
|
56
|
+
}
|
|
57
|
+
;
|
|
58
|
+
},
|
|
59
|
+
/** Read JSON files */
|
|
60
|
+
readJSON = (file, internal) => {
|
|
61
|
+
try {
|
|
62
|
+
const data = readData(file, internal);
|
|
63
|
+
return data ? JSON.parse(data) : undefined;
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
console.log(`failed to read JSON at`, file);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
;
|
|
70
|
+
}, metaTags = ({ author, websiteDescription, websiteName, websiteTitle, coverImageLink, coverImageDescription, publishedTime, websiteLink, dataString, theme_color, twitterUserName, appIconFile, noindex, language, isHome, keywords, }) => {
|
|
71
|
+
const titleText = isHome ? `${websiteName} | ${websiteTitle}`
|
|
72
|
+
: `${websiteTitle} | ${websiteName}`;
|
|
73
|
+
return {
|
|
74
|
+
// Character Encoding and Content
|
|
75
|
+
charset: {
|
|
76
|
+
charset: 'UTF-8',
|
|
77
|
+
},
|
|
78
|
+
"http-equiv:content-type": {
|
|
79
|
+
"http-equiv": "Content-Type",
|
|
80
|
+
content: "text/html; charset=UTF-8",
|
|
81
|
+
},
|
|
82
|
+
// Viewport and Device Compatibility
|
|
83
|
+
viewport: `width=device-width, initial-scale=1.0`,
|
|
84
|
+
'http-equiv:X-UA-Compatible': {
|
|
85
|
+
'http-equiv': `X-UA-Compatible`,
|
|
86
|
+
content: `ie=edge`,
|
|
87
|
+
},
|
|
88
|
+
"mobile-web-app-capable": "yes",
|
|
89
|
+
"apple-mobile-web-app-capable": "yes",
|
|
90
|
+
"apple-mobile-web-app-status-bar-style": "black",
|
|
91
|
+
// SEO Indexing
|
|
92
|
+
robots: noindex ? `noindex` : `index,follow`,
|
|
93
|
+
referrer: "origin",
|
|
94
|
+
'googlebot-news': noindex ? `noindex` : `index,follow`,
|
|
95
|
+
// Name and Title
|
|
96
|
+
"apple-mobile-web-app-title": websiteName,
|
|
97
|
+
author,
|
|
98
|
+
description: websiteDescription,
|
|
99
|
+
...keywords ? { keywords, news_keywords: keywords } : {},
|
|
100
|
+
// Open Graph (OG)
|
|
101
|
+
'og:type': {
|
|
102
|
+
property: 'og:type',
|
|
103
|
+
content: `website`,
|
|
104
|
+
name: `type`,
|
|
105
|
+
},
|
|
106
|
+
"og:locale": {
|
|
107
|
+
property: "og:locale",
|
|
108
|
+
content: language,
|
|
109
|
+
},
|
|
110
|
+
'og:title': {
|
|
111
|
+
property: 'og:title',
|
|
112
|
+
content: titleText,
|
|
113
|
+
name: `title`,
|
|
114
|
+
},
|
|
115
|
+
"og:site_name": {
|
|
116
|
+
property: "og:site_name",
|
|
117
|
+
content: websiteName,
|
|
118
|
+
},
|
|
119
|
+
'og:description': {
|
|
120
|
+
property: 'og:description',
|
|
121
|
+
content: `${websiteDescription}`,
|
|
122
|
+
name: `description`,
|
|
123
|
+
},
|
|
124
|
+
'og:publish_date': {
|
|
125
|
+
content: publishedTime,
|
|
126
|
+
property: `og:publish_date`,
|
|
127
|
+
name: `publish_date`,
|
|
128
|
+
},
|
|
129
|
+
'og:modified_date': {
|
|
130
|
+
content: dataString,
|
|
131
|
+
property: `og:modified_date`,
|
|
132
|
+
name: `modified_date`,
|
|
133
|
+
},
|
|
134
|
+
'og:url': {
|
|
135
|
+
content: websiteLink,
|
|
136
|
+
property: `og:url`,
|
|
137
|
+
name: `url`,
|
|
138
|
+
},
|
|
139
|
+
'og:image': {
|
|
140
|
+
property: 'og:image',
|
|
141
|
+
content: coverImageLink,
|
|
142
|
+
name: `image`,
|
|
143
|
+
},
|
|
144
|
+
"og:image:alt": {
|
|
145
|
+
property: "og:image:alt",
|
|
146
|
+
content: coverImageDescription,
|
|
147
|
+
},
|
|
148
|
+
// Twitter Tags
|
|
149
|
+
'twitter:card': {
|
|
150
|
+
property: 'twitter:card',
|
|
151
|
+
content: `summary_large_image`
|
|
152
|
+
},
|
|
153
|
+
'twitter:site': {
|
|
154
|
+
property: 'twitter:site',
|
|
155
|
+
content: `@${twitterUserName}`,
|
|
156
|
+
},
|
|
157
|
+
'twitter:title': {
|
|
158
|
+
property: 'twitter:title',
|
|
159
|
+
content: titleText
|
|
160
|
+
},
|
|
161
|
+
'twitter:description': {
|
|
162
|
+
property: 'twitter:description',
|
|
163
|
+
content: websiteDescription,
|
|
164
|
+
},
|
|
165
|
+
'twitter:image': {
|
|
166
|
+
property: 'twitter:image',
|
|
167
|
+
content: coverImageLink,
|
|
168
|
+
},
|
|
169
|
+
'twitter:image:alt': {
|
|
170
|
+
property: 'twitter:image:alt',
|
|
171
|
+
content: coverImageDescription,
|
|
172
|
+
},
|
|
173
|
+
// App Icons
|
|
174
|
+
"favicon-32": {
|
|
175
|
+
href: appIconFile,
|
|
176
|
+
rel: "icon",
|
|
177
|
+
type: "image/png",
|
|
178
|
+
sizes: "32x32",
|
|
179
|
+
},
|
|
180
|
+
"favicon-128": {
|
|
181
|
+
href: appIconFile,
|
|
182
|
+
rel: "icon",
|
|
183
|
+
type: "image/png",
|
|
184
|
+
sizes: "128x128",
|
|
185
|
+
},
|
|
186
|
+
"favicon-180": {
|
|
187
|
+
href: appIconFile,
|
|
188
|
+
rel: "icon",
|
|
189
|
+
type: "image/png",
|
|
190
|
+
sizes: "180x180",
|
|
191
|
+
},
|
|
192
|
+
"favicon-192": {
|
|
193
|
+
href: appIconFile,
|
|
194
|
+
rel: "icon",
|
|
195
|
+
type: "image/png",
|
|
196
|
+
sizes: "192x192",
|
|
197
|
+
},
|
|
198
|
+
"shortcut-icon-196": {
|
|
199
|
+
href: appIconFile,
|
|
200
|
+
rel: "shortcut icon",
|
|
201
|
+
type: "image/png",
|
|
202
|
+
sizes: "196x196",
|
|
203
|
+
},
|
|
204
|
+
"shortcut-icon-512": {
|
|
205
|
+
href: appIconFile,
|
|
206
|
+
rel: "shortcut icon",
|
|
207
|
+
type: "image/png",
|
|
208
|
+
sizes: "512x512",
|
|
209
|
+
},
|
|
210
|
+
"apple-touch-icon-120": {
|
|
211
|
+
href: appIconFile,
|
|
212
|
+
rel: "apple-touch-icon",
|
|
213
|
+
type: "image/png",
|
|
214
|
+
sizes: "120x120",
|
|
215
|
+
},
|
|
216
|
+
"apple-touch-icon-152": {
|
|
217
|
+
href: appIconFile,
|
|
218
|
+
rel: "apple-touch-icon",
|
|
219
|
+
type: "image/png",
|
|
220
|
+
sizes: "152x152",
|
|
221
|
+
},
|
|
222
|
+
"apple-touch-icon-180": {
|
|
223
|
+
href: appIconFile,
|
|
224
|
+
rel: "apple-touch-icon",
|
|
225
|
+
type: "image/png",
|
|
226
|
+
sizes: "180x180",
|
|
227
|
+
},
|
|
228
|
+
"apple-touch-icon-512": {
|
|
229
|
+
href: appIconFile,
|
|
230
|
+
rel: "apple-touch-icon",
|
|
231
|
+
type: "image/png",
|
|
232
|
+
sizes: "512x512",
|
|
233
|
+
},
|
|
234
|
+
// Image and Thumbnail
|
|
235
|
+
'article:published_time': {
|
|
236
|
+
property: 'article:published_time',
|
|
237
|
+
content: publishedTime
|
|
238
|
+
},
|
|
239
|
+
'article:modified_time': {
|
|
240
|
+
property: 'article:modified_time',
|
|
241
|
+
content: dataString
|
|
242
|
+
},
|
|
243
|
+
thumbnailUrl: {
|
|
244
|
+
itemprop: `thumbnailUrl`,
|
|
245
|
+
content: coverImageLink
|
|
246
|
+
},
|
|
247
|
+
image: {
|
|
248
|
+
itemprop: `image`,
|
|
249
|
+
content: coverImageLink
|
|
250
|
+
},
|
|
251
|
+
// Cache and Security
|
|
252
|
+
"http-equiv:cache-control": {
|
|
253
|
+
"http-equiv": "Cache-control",
|
|
254
|
+
content: "NO-STORE",
|
|
255
|
+
},
|
|
256
|
+
"http-equiv:content-security-policy": {
|
|
257
|
+
"http-equiv": "Content-Security-Policy",
|
|
258
|
+
content: "",
|
|
259
|
+
},
|
|
260
|
+
// Theme
|
|
261
|
+
"theme-color": theme_color,
|
|
262
|
+
};
|
|
263
|
+
}, linkTags = ({ favIconFile, timeNow, coverImageLink, canonicalURL, }) => `
|
|
264
|
+
<link rel="icon" href="${favIconFile}" type="image/x-icon">
|
|
265
|
+
<link rel="manifest" href="/app.json?v=${timeNow}">
|
|
266
|
+
<link rel="image_src" href="${coverImageLink}">
|
|
267
|
+
<link rel="canonical" href="${canonicalURL}">\n`,
|
|
268
|
+
/** Check for PHP tag */
|
|
269
|
+
isPHPTag = (code) => code?.includes(`<?php`);
|
|
270
|
+
exports.writeData = writeData;
|
|
271
|
+
exports.writeJSON = writeJSON;
|
|
272
|
+
exports.readData = readData;
|
|
273
|
+
exports.readJSON = readJSON;
|
|
274
|
+
exports.metaTags = metaTags;
|
|
275
|
+
exports.linkTags = linkTags;
|
|
276
|
+
exports.isPHPTag = isPHPTag;
|