@sovereignbase/pwa 0.0.1 → 1.0.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.
- package/LICENSE +200 -200
- package/README.md +109 -0
- package/dist/{htmlDocument-Cx-dprM5.cjs → htmlDocument-C3k13Sjr.cjs} +3 -10
- package/dist/htmlDocument-C3k13Sjr.cjs.map +1 -0
- package/dist/{htmlDocument-DABSNDvf.js → htmlDocument-C533Sj5O.js} +3 -10
- package/dist/htmlDocument-C533Sj5O.js.map +1 -0
- package/dist/index.cjs +218 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -109
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +60 -109
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +220 -41
- package/dist/index.js.map +1 -1
- package/dist/serviceWorker/entrypoint.cjs +13 -12
- package/dist/serviceWorker/entrypoint.cjs.map +1 -1
- package/dist/serviceWorker/entrypoint.js +13 -12
- package/dist/serviceWorker/entrypoint.js.map +1 -1
- package/package.json +1 -4
- package/dist/htmlDocument-Cx-dprM5.cjs.map +0 -1
- package/dist/htmlDocument-DABSNDvf.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"htmlDocument-C533Sj5O.js","names":["seo.jsonLDMarkup","seo.languageLinksMarkup","seo.ogMarkup","seo.twitterMarkup"],"sources":["../src/seoComponents/jsonldMarkup.ts","../src/seoComponents/languageLinksMarkup.ts","../src/seoComponents/ogMarkup.ts","../src/seoComponents/twitterMarkup.ts","../src/htmlDocument/index.ts"],"sourcesContent":["import type { JSONLDMarkup } from '../.types/index.js'\n\n/**\n * Generates Schema.org JSON-LD markup describing a website,\n * its web application, the current localized page, and publisher.\n */\nexport const jsonLDMarkup = ({\n site,\n application,\n page,\n organization,\n}: JSONLDMarkup) => {\n const siteId = `${site.url}#website`\n const applicationId = `${application.url}#application`\n const organizationId = `${organization.url}#organization`\n const pageId = `${page.url}#webpage`\n\n const data = {\n '@context': 'https://schema.org',\n '@graph': [\n {\n '@type': 'WebSite',\n '@id': siteId,\n name: site.name,\n url: site.url,\n publisher: {\n '@id': organizationId,\n },\n },\n\n {\n '@type': 'WebApplication',\n '@id': applicationId,\n name: application.name,\n url: application.url,\n inLanguage: application.inLanguage,\n\n ...(application.applicationCategory\n ? { applicationCategory: application.applicationCategory }\n : {}),\n\n ...(application.operatingSystem\n ? { operatingSystem: application.operatingSystem }\n : {}),\n\n ...(application.browserRequirements\n ? { browserRequirements: application.browserRequirements }\n : {}),\n\n ...(application.featureList\n ? { featureList: application.featureList }\n : {}),\n\n ...(application.screenshot\n ? { screenshot: application.screenshot }\n : {}),\n\n publisher: {\n '@id': organizationId,\n },\n },\n\n {\n '@type': 'WebPage',\n '@id': pageId,\n name: page.name,\n description: page.description,\n url: page.url,\n inLanguage: page.inLanguage,\n\n isPartOf: {\n '@id': siteId,\n },\n\n mainEntity: {\n '@id': applicationId,\n },\n },\n\n {\n '@type': 'Organization',\n '@id': organizationId,\n name: organization.name,\n url: organization.url,\n logo: {\n '@type': 'ImageObject',\n url: organization.logo,\n },\n },\n ],\n }\n\n return `\n <script type=\"application/ld+json\">\n${JSON.stringify(data).replaceAll('<', '\\\\u003c')}\n </script>\n`\n}\n","import type { BCP47LanguageTag } from '@sovereignbase/utils'\n\n/**\n * Generates canonical and language-alternate link markup for a localized page.\n *\n * Produces:\n * - a canonical link for the current language,\n * - `hreflang` alternate links for each supported alternate language,\n * - an `x-default` alternate link for the default language.\n *\n * @param host Registrable domain, such as `example.com` or `example.co.uk`.\n * @param defaultLanguage Language used for the `x-default` URL.\n * @param canonicalLanguage Language used for the canonical URL.\n * @param alternateLanguages Languages exposed through `hreflang` alternate links.\n * @param pathSuffix Optional path suffix starting with `/`.\n */\nexport const languageLinksMarkup = (\n host: `${string /* domain */}.${string /* public suffix */}`,\n defaultLanguage: BCP47LanguageTag,\n canonicalLanguage: BCP47LanguageTag,\n alternateLanguages: BCP47LanguageTag[],\n pathSuffix: '' | `/${string}` = ''\n) => `\n <link rel=\"canonical\" href=\"https://${host}/${canonicalLanguage}${pathSuffix}\" />\n ${(() => {\n let markup = ``\n for (const language of alternateLanguages)\n markup += ` <link rel=\"alternate\" hreflang=\"${language}\" href=\"https://${host}/${language}${pathSuffix}\" />`\n return markup\n })()}\n <link rel=\"alternate\" hreflang=\"x-default\" href=\"https://${host}/${defaultLanguage}${pathSuffix}\" />\n`\n","import type { OpenGraphLocale } from '@sovereignbase/utils'\n\n/**\n * Generates Open Graph metadata markup.\n *\n * @param locale Open Graph locale, such as `fi_FI` or `en_US`.\n * @param siteName Site or application name.\n * @param title Page title.\n * @param description Page description.\n * @param url Canonical URL of the page.\n * @param imageUrl URL of the social sharing image.\n * @param imageAlt Alternative text for the social sharing image.\n * @param imageWidth Width of the social sharing image in pixels.\n * @param imageHeight Height of the social sharing image in pixels.\n */\nexport const ogMarkup = (\n locale: OpenGraphLocale,\n siteName: string,\n title: string,\n description: string,\n url: `https://${string}`,\n imageUrl: string,\n imageAlt: string,\n imageWidth: number = 1200,\n imageHeight: number = 630\n) => `\n <meta property=\"og:locale\" content=\"${locale}\" />\n <meta property=\"og:type\" content=\"website\" />\n <meta property=\"og:site_name\" content=\"${siteName}\" />\n <meta property=\"og:title\" content=\"${title}\" />\n <meta property=\"og:description\" content=\"${description}\" />\n <meta property=\"og:url\" content=\"${url}\" />\n <meta property=\"og:image\" content=\"${imageUrl}\" />\n <meta property=\"og:image:width\" content=\"${imageWidth}\" />\n <meta property=\"og:image:height\" content=\"${imageHeight}\" />\n <meta property=\"og:image:alt\" content=\"${imageAlt}\" />\n`\n","/**\n * Generates Twitter Card metadata markup.\n *\n * @param title Page title.\n * @param description Page description.\n * @param url Canonical URL of the page.\n * @param imageUrl URL of the social sharing image.\n * @param imageAlt Alternative text for the social sharing image.\n * @param site Twitter/X handle of the site.\n * @param creator Twitter/X handle of the content creator.\n */\nexport const twitterMarkup = (\n title: string,\n description: string,\n url: `https://${string}`,\n imageUrl: string,\n imageAlt: string,\n site: `@${string}`,\n creator: `@${string}`\n) => `\n <meta name=\"twitter:card\" content=\"summary_large_image\" />\n <meta name=\"twitter:title\" content=\"${title}\" />\n <meta name=\"twitter:description\" content=\"${description}\" />\n <meta name=\"twitter:url\" content=\"${url}\" />\n <meta name=\"twitter:image\" content=\"${imageUrl}\" />\n <meta name=\"twitter:image:alt\" content=\"${imageAlt}\" />\n <meta name=\"twitter:site\" content=\"${site}\" />\n <meta name=\"twitter:creator\" content=\"${creator}\" />\n`\n","import { DocumentMarkupOptions } from '../.types/index.js'\nimport * as seo from '../seoComponents/index.js'\n/**\n * Generates a complete HTML document for a web application.\n *\n * Supports:\n * - localized document language,\n * - application and theme metadata,\n * - Web App Manifest integration,\n * - favicon and Apple/Safari application icons,\n * - critical inline styles,\n * - inline ES module initialization,\n * - arbitrary additional head markup.\n */\nexport const documentMarkup = async ({\n language,\n title,\n applicationName,\n themeColor,\n bodyMarkup = '',\n headMarkup = '',\n stylesheet = '',\n entrypoint = '',\n iconUrl,\n appleTouchIconUrl,\n maskIconUrl,\n manifestUrl,\n maskIconColor = themeColor,\n colorScheme = 'light dark',\n appleStatusBarStyle = 'black-translucent',\n seo: documentSEO,\n}: DocumentMarkupOptions): Promise<string> =>\n `<!DOCTYPE html>\n<html lang=\"${language}\">\n <head>\n <meta charset=\"UTF-8\" />\n <title>${title}</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n\n <meta name=\"application-name\" content=\"${applicationName}\" />\n <meta name=\"color-scheme\" content=\"${colorScheme}\" />\n <meta name=\"theme-color\" content=\"${themeColor}\" />\n\n <meta name=\"mobile-web-app-capable\" content=\"yes\" />\n <meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n <meta name=\"apple-mobile-web-app-title\" content=\"${applicationName}\" />\n <meta\n name=\"apple-mobile-web-app-status-bar-style\"\n content=\"${appleStatusBarStyle}\"\n />\n\n ${iconUrl ? `<link rel=\"icon\" href=\"${iconUrl}\" />` : ''}\n ${\n appleTouchIconUrl\n ? `<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"${appleTouchIconUrl}\" />`\n : ''\n }\n ${\n maskIconUrl\n ? `<link rel=\"mask-icon\" href=\"${maskIconUrl}\" color=\"${maskIconColor}\" />`\n : ''\n }\n ${manifestUrl ? `<link rel=\"manifest\" href=\"${manifestUrl}\" />` : ''}\n\n ${seo.jsonLDMarkup(documentSEO.jsonLD)}\n ${seo.languageLinksMarkup(\n documentSEO.languageLinks.host,\n documentSEO.languageLinks.defaultLanguage,\n documentSEO.languageLinks.canonicalLanguage,\n documentSEO.languageLinks.alternateLanguages,\n documentSEO.languageLinks.pathSuffix\n )}\n ${seo.ogMarkup(\n documentSEO.openGraph.locale,\n documentSEO.openGraph.siteName,\n documentSEO.openGraph.title,\n documentSEO.openGraph.description,\n documentSEO.openGraph.url,\n documentSEO.openGraph.imageUrl,\n documentSEO.openGraph.imageAlt,\n documentSEO.openGraph.imageWidth,\n documentSEO.openGraph.imageHeight\n )}\n ${seo.twitterMarkup(\n documentSEO.twitter.title,\n documentSEO.twitter.description,\n documentSEO.twitter.url,\n documentSEO.twitter.imageUrl,\n documentSEO.twitter.imageAlt,\n documentSEO.twitter.site,\n documentSEO.twitter.creator\n )}\n\n ${headMarkup}\n\n ${\n stylesheet\n ? `<style>\n${stylesheet}\n </style>`\n : ''\n }\n\n </head>\n <body>\n${bodyMarkup}\n${\n entrypoint\n ? `<script type=\"module\">\n${entrypoint}\n </script>`\n : ''\n}\n </body>\n</html>`\n .replace(/>\\s+</g, '><')\n .trim()\n"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
18
|
-
const require_htmlDocument = require("./htmlDocument-
|
|
18
|
+
const require_htmlDocument = require("./htmlDocument-C3k13Sjr.cjs");
|
|
19
|
+
let node_crypto = require("node:crypto");
|
|
19
20
|
let node_fs = require("node:fs");
|
|
20
21
|
let node_fs_promises = require("node:fs/promises");
|
|
21
22
|
let node_path = require("node:path");
|
|
@@ -25,6 +26,7 @@ let html_minifier_terser = require("html-minifier-terser");
|
|
|
25
26
|
let node_url = require("node:url");
|
|
26
27
|
let terser = require("terser");
|
|
27
28
|
//#region src/minifyCss/index.ts
|
|
29
|
+
const minifiedOutputs$2 = /* @__PURE__ */ new Map();
|
|
28
30
|
/** Bundles and minifies a CSS entrypoint into a dense string. */
|
|
29
31
|
async function minifyCss(entrypoint) {
|
|
30
32
|
const bundled = await (0, esbuild.build)({
|
|
@@ -33,20 +35,29 @@ async function minifyCss(entrypoint) {
|
|
|
33
35
|
legalComments: "none",
|
|
34
36
|
minify: true,
|
|
35
37
|
treeShaking: true,
|
|
36
|
-
write: false
|
|
38
|
+
write: false,
|
|
39
|
+
external: ["/assets/*"]
|
|
37
40
|
});
|
|
41
|
+
const source = bundled.outputFiles[0].text;
|
|
42
|
+
const cached = minifiedOutputs$2.get(source);
|
|
43
|
+
if (cached !== void 0) return cached;
|
|
38
44
|
const { code } = (0, lightningcss.transform)({
|
|
39
45
|
code: bundled.outputFiles[0].contents,
|
|
40
46
|
filename: entrypoint.toString(),
|
|
41
47
|
minify: true
|
|
42
48
|
});
|
|
43
|
-
|
|
49
|
+
const output = new TextDecoder().decode(code).trim();
|
|
50
|
+
minifiedOutputs$2.set(source, output);
|
|
51
|
+
return output;
|
|
44
52
|
}
|
|
45
53
|
//#endregion
|
|
46
54
|
//#region src/minifyHtml/index.ts
|
|
55
|
+
const minifiedOutputs$1 = /* @__PURE__ */ new Map();
|
|
47
56
|
/** Minifies a complete HTML document, including inline CSS and JavaScript. */
|
|
48
57
|
async function minifyHtml(source) {
|
|
49
|
-
|
|
58
|
+
const cached = minifiedOutputs$1.get(source);
|
|
59
|
+
if (cached !== void 0) return cached;
|
|
60
|
+
const output = await (0, html_minifier_terser.minify)(source, {
|
|
50
61
|
collapseBooleanAttributes: true,
|
|
51
62
|
collapseInlineTagWhitespace: true,
|
|
52
63
|
collapseWhitespace: true,
|
|
@@ -72,17 +83,21 @@ async function minifyHtml(source) {
|
|
|
72
83
|
sortClassName: true,
|
|
73
84
|
useShortDoctype: true
|
|
74
85
|
});
|
|
86
|
+
minifiedOutputs$1.set(source, output);
|
|
87
|
+
return output;
|
|
75
88
|
}
|
|
76
89
|
//#endregion
|
|
77
90
|
//#region src/minifyJs/index.ts
|
|
91
|
+
const minifiedOutputs = /* @__PURE__ */ new Map();
|
|
78
92
|
/** Bundles, tree-shakes, mangles, and repeatedly minifies JavaScript. */
|
|
79
|
-
async function minifyJs(input, { define, passes = 3 } = {}) {
|
|
80
|
-
|
|
93
|
+
async function minifyJs(input, { banner, define, passes = 3 } = {}) {
|
|
94
|
+
const output = (await (0, esbuild.build)({
|
|
81
95
|
...typeof input === "object" && "source" in input ? { stdin: {
|
|
82
96
|
contents: input.source,
|
|
83
97
|
resolveDir: process.cwd()
|
|
84
98
|
} } : { entryPoints: [input instanceof URL ? (0, node_url.fileURLToPath)(input) : input.toString()] },
|
|
85
99
|
bundle: true,
|
|
100
|
+
banner: banner === void 0 ? void 0 : { js: banner },
|
|
86
101
|
define,
|
|
87
102
|
format: "esm",
|
|
88
103
|
legalComments: "none",
|
|
@@ -91,6 +106,15 @@ async function minifyJs(input, { define, passes = 3 } = {}) {
|
|
|
91
106
|
treeShaking: true,
|
|
92
107
|
write: false
|
|
93
108
|
})).outputFiles[0].text;
|
|
109
|
+
const cacheKey = `${passes}\0${output}`;
|
|
110
|
+
const cached = minifiedOutputs.get(cacheKey);
|
|
111
|
+
if (cached !== void 0) return cached;
|
|
112
|
+
const result = await repeatedlyMinify(output, passes);
|
|
113
|
+
minifiedOutputs.set(cacheKey, result);
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
async function repeatedlyMinify(source, passes) {
|
|
117
|
+
let output = source;
|
|
94
118
|
for (let round = 0; round < passes; round += 1) {
|
|
95
119
|
const result = await (0, terser.minify)(output, {
|
|
96
120
|
compress: {
|
|
@@ -108,6 +132,7 @@ async function minifyJs(input, { define, passes = 3 } = {}) {
|
|
|
108
132
|
module: true,
|
|
109
133
|
toplevel: true
|
|
110
134
|
});
|
|
135
|
+
/* v8 ignore next 3 -- Terser returns code or rejects for this input form. */
|
|
111
136
|
if (result.code === void 0) throw new Error("Terser did not produce JavaScript output");
|
|
112
137
|
output = result.code;
|
|
113
138
|
}
|
|
@@ -158,35 +183,34 @@ const webManifest = ({ name, shortName, description, startUrl, themeColor, icon1
|
|
|
158
183
|
//#region src/index.ts
|
|
159
184
|
async function pwaize(config) {
|
|
160
185
|
const outputDirectory = (0, node_path.join)(config.outDir.toString(), "web");
|
|
161
|
-
const
|
|
186
|
+
const languages = [.../* @__PURE__ */ new Set([config.defaultLanguage, ...config.alternateLanguages])];
|
|
162
187
|
const minifyPasses = config.minifyPasses ?? 3;
|
|
163
188
|
const serviceWorkerPath = "/ServiceWorker";
|
|
164
189
|
await (0, node_fs_promises.mkdir)(outputDirectory, { recursive: true });
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const sourceDirectory = directory.toString();
|
|
190
|
+
if (config.assetsDir !== void 0) {
|
|
191
|
+
const sourceDirectory = config.assetsDir.toString();
|
|
168
192
|
await (0, node_fs_promises.cp)(sourceDirectory, (0, node_path.join)(outputDirectory, (0, node_path.basename)(sourceDirectory)), { recursive: true });
|
|
169
193
|
}
|
|
194
|
+
if (config.i18nDir !== void 0) {
|
|
195
|
+
const sourceDirectory = config.i18nDir.toString();
|
|
196
|
+
await buildScriptDirectory(sourceDirectory, (0, node_path.join)(outputDirectory, (0, node_path.basename)(sourceDirectory)), minifyPasses);
|
|
197
|
+
}
|
|
170
198
|
const stylesheet = await minifyCss(config.stylesheet);
|
|
171
199
|
const entrypoint = await minifyJs(config.entrypoint, { passes: minifyPasses });
|
|
172
|
-
const installer = await minifyJs({ source: `
|
|
173
|
-
const
|
|
200
|
+
const installer = await minifyJs({ source: `await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:"/",type:"module"});await navigator.serviceWorker.ready;location.reload();` }, { passes: minifyPasses });
|
|
201
|
+
const documentOptions = {};
|
|
174
202
|
for (const language of languages) {
|
|
175
|
-
const localized = config
|
|
176
|
-
if (localized === void 0) throw new Error(`Missing PWA configuration for language "${language}"`);
|
|
203
|
+
const localized = localizeConfig(config, language, languages);
|
|
177
204
|
const languageDirectory = (0, node_path.join)(outputDirectory, language);
|
|
178
205
|
const manifestPath = `/${language}/manifest.webmanifest`;
|
|
179
|
-
const manifest = webManifest(
|
|
180
|
-
|
|
181
|
-
lang: language
|
|
182
|
-
});
|
|
206
|
+
const manifest = webManifest(localized.manifest);
|
|
207
|
+
documentOptions[language] = localized.document;
|
|
183
208
|
await (0, node_fs_promises.mkdir)(languageDirectory, { recursive: true });
|
|
184
209
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(languageDirectory, "manifest.webmanifest"), manifest);
|
|
185
210
|
const installerDocument = await minifyHtml(await require_htmlDocument.documentMarkup({
|
|
186
211
|
...localized.document,
|
|
187
|
-
language,
|
|
188
|
-
stylesheet: "",
|
|
189
212
|
entrypoint: installer,
|
|
213
|
+
language,
|
|
190
214
|
manifestUrl: manifestPath
|
|
191
215
|
}));
|
|
192
216
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(languageDirectory, "index.html"), installerDocument);
|
|
@@ -195,30 +219,73 @@ async function pwaize(config) {
|
|
|
195
219
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(outputDirectory, "manifest.webmanifest"), manifest);
|
|
196
220
|
}
|
|
197
221
|
}
|
|
198
|
-
const buildIdPath = (0, node_path.join)(outputDirectory, "@sovereignbase", "pwa", "pwaize-build-id.txt");
|
|
199
|
-
await (0, node_fs_promises.mkdir)((0, node_path.join)(outputDirectory, "@sovereignbase", "pwa"), { recursive: true });
|
|
200
|
-
await (0, node_fs_promises.writeFile)(buildIdPath, buildId);
|
|
201
222
|
if (config._headersFile === true) await (0, node_fs_promises.writeFile)((0, node_path.join)(outputDirectory, "_headers"), `/${serviceWorkerPath.slice(1)}\n Cache-Control: no-cache\n Content-Type: text/javascript;charset=UTF-8\n\n/*\n X-Content-Type-Options: nosniff\n`);
|
|
202
|
-
const
|
|
223
|
+
const buildIdUrl = "/@sovereignbase/pwa/pwaize-build-id.txt";
|
|
224
|
+
const generatedFiles = (await publicFiles(outputDirectory)).filter((url) => url !== serviceWorkerPath && url !== buildIdUrl);
|
|
225
|
+
const precache = [.../* @__PURE__ */ new Set([...generatedFiles, ...config.serviceWorker?.precache ?? []])].sort();
|
|
203
226
|
const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule);
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
entrypoint: JSON.stringify(entrypoint),
|
|
215
|
-
precache: JSON.stringify(precache),
|
|
216
|
-
stylesheet: JSON.stringify(stylesheet)
|
|
217
|
-
},
|
|
218
|
-
passes: minifyPasses
|
|
227
|
+
const initialize = config.serviceWorker?.initialize === void 0 ? "undefined" : functionExpression(config.serviceWorker.initialize);
|
|
228
|
+
const waitUntil = config.serviceWorker?.waitUntil === void 0 ? "undefined" : functionExpression(config.serviceWorker.waitUntil);
|
|
229
|
+
const buildId = await contentBuildId(outputDirectory, generatedFiles, {
|
|
230
|
+
bypassRules,
|
|
231
|
+
documentOptions,
|
|
232
|
+
entrypoint,
|
|
233
|
+
initialize,
|
|
234
|
+
precache,
|
|
235
|
+
stylesheet,
|
|
236
|
+
waitUntil
|
|
219
237
|
});
|
|
238
|
+
const buildIdDirectory = (0, node_path.join)(outputDirectory, "@sovereignbase", "pwa");
|
|
239
|
+
await (0, node_fs_promises.mkdir)(buildIdDirectory, { recursive: true });
|
|
240
|
+
await (0, node_fs_promises.writeFile)((0, node_path.join)(buildIdDirectory, "pwaize-build-id.txt"), buildId);
|
|
241
|
+
const compiledServiceWorker = new URL("./serviceWorker/entrypoint.js", require("url").pathToFileURL(__filename).href);
|
|
242
|
+
const serviceWorker = await minifyJs(
|
|
243
|
+
/* v8 ignore next -- the packaged .js path is exercised by runtime tests */
|
|
244
|
+
(0, node_fs.existsSync)(compiledServiceWorker) ? compiledServiceWorker : new URL("./serviceWorker/entrypoint.ts", require("url").pathToFileURL(__filename).href),
|
|
245
|
+
{
|
|
246
|
+
banner: `const __pwaInitialize=${initialize},__pwaWaitUntil=${waitUntil};`,
|
|
247
|
+
define: {
|
|
248
|
+
buildId: JSON.stringify(buildId),
|
|
249
|
+
buildIdUrl: JSON.stringify(buildIdUrl),
|
|
250
|
+
bypassRules: JSON.stringify(bypassRules),
|
|
251
|
+
customInitialize: "__pwaInitialize",
|
|
252
|
+
customWaitUntil: "__pwaWaitUntil",
|
|
253
|
+
defaultLanguage: JSON.stringify(config.defaultLanguage),
|
|
254
|
+
documentOptions: JSON.stringify(documentOptions),
|
|
255
|
+
entrypoint: JSON.stringify(entrypoint),
|
|
256
|
+
precache: JSON.stringify(precache),
|
|
257
|
+
stylesheet: JSON.stringify(stylesheet)
|
|
258
|
+
},
|
|
259
|
+
passes: minifyPasses
|
|
260
|
+
}
|
|
261
|
+
);
|
|
220
262
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(outputDirectory, serviceWorkerPath.slice(1)), serviceWorker);
|
|
221
263
|
}
|
|
264
|
+
async function buildScriptDirectory(sourceDirectory, outputDirectory, passes, root = sourceDirectory) {
|
|
265
|
+
for (const entry of await (0, node_fs_promises.readdir)(sourceDirectory, { withFileTypes: true })) {
|
|
266
|
+
const source = (0, node_path.join)(sourceDirectory, entry.name);
|
|
267
|
+
if (entry.isDirectory()) {
|
|
268
|
+
await buildScriptDirectory(source, outputDirectory, passes, root);
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (!entry.isFile() || entry.name.endsWith(".d.ts")) continue;
|
|
272
|
+
const relativePath = (0, node_path.relative)(root, source);
|
|
273
|
+
const extension = (0, node_path.extname)(relativePath);
|
|
274
|
+
const output = (0, node_path.join)(outputDirectory, /\.[cm]?[jt]sx?$/.test(extension) ? `${relativePath.slice(0, -extension.length)}.js` : relativePath);
|
|
275
|
+
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(output), { recursive: true });
|
|
276
|
+
if (/\.[cm]?[jt]sx?$/.test(extension)) await (0, node_fs_promises.writeFile)(output, await minifyJs(source, { passes }));
|
|
277
|
+
else await (0, node_fs_promises.cp)(source, output);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
async function contentBuildId(outputDirectory, files, configuration) {
|
|
281
|
+
const hash = (0, node_crypto.createHash)("sha256");
|
|
282
|
+
hash.update(JSON.stringify(configuration));
|
|
283
|
+
for (const file of files) {
|
|
284
|
+
hash.update(file);
|
|
285
|
+
hash.update(await (0, node_fs_promises.readFile)((0, node_path.join)(outputDirectory, ...file.slice(1).split("/"))));
|
|
286
|
+
}
|
|
287
|
+
return hash.digest("hex");
|
|
288
|
+
}
|
|
222
289
|
async function publicFiles(directory, root = directory) {
|
|
223
290
|
const entries = await (0, node_fs_promises.readdir)(directory, { withFileTypes: true });
|
|
224
291
|
const files = [];
|
|
@@ -252,6 +319,118 @@ function globRule(pattern) {
|
|
|
252
319
|
source: `${source}$`
|
|
253
320
|
};
|
|
254
321
|
}
|
|
322
|
+
function functionExpression(callback) {
|
|
323
|
+
const source = callback.toString();
|
|
324
|
+
if (/^(?:async\s+)?function\b|^(?:async\s+)?\(/.test(source)) return `(${source})`;
|
|
325
|
+
if (source.startsWith("async ")) return `(async function ${source.slice(6)})`;
|
|
326
|
+
return `(function ${source})`;
|
|
327
|
+
}
|
|
328
|
+
function localizeConfig(config, language, languages) {
|
|
329
|
+
const get = (value, empty) => localizedValue(value, language, config.defaultLanguage, empty);
|
|
330
|
+
const applicationName = get(config.applicationName, "");
|
|
331
|
+
const description = get(config.description, "");
|
|
332
|
+
const icon192 = get(config.icons.icon192, "");
|
|
333
|
+
const icon512 = get(config.icons.icon512, "");
|
|
334
|
+
const origin = get(config.origin, "");
|
|
335
|
+
const pageUrl = origin === "" ? "" : new URL(`/${language}`, origin).href;
|
|
336
|
+
const organizationLogo = origin === "" || icon512 === "" ? "" : new URL(icon512, origin).href;
|
|
337
|
+
const themeColor = get(config.themeColor, "");
|
|
338
|
+
const title = get(config.title, "");
|
|
339
|
+
return {
|
|
340
|
+
document: {
|
|
341
|
+
applicationName,
|
|
342
|
+
appleStatusBarStyle: get(config.appleStatusBarStyle, "black-translucent"),
|
|
343
|
+
appleTouchIconUrl: get(config.icons.appleTouchIconUrl, icon192),
|
|
344
|
+
bodyMarkup: get(config.bodyMarkup, ""),
|
|
345
|
+
colorScheme: get(config.colorScheme, "light dark"),
|
|
346
|
+
headMarkup: get(config.headMarkup, ""),
|
|
347
|
+
iconUrl: get(config.icons.iconUrl, icon512),
|
|
348
|
+
maskIconColor: themeColor,
|
|
349
|
+
maskIconUrl: get(config.icons.maskIconUrl, ""),
|
|
350
|
+
seo: {
|
|
351
|
+
jsonLD: {
|
|
352
|
+
application: {
|
|
353
|
+
applicationCategory: get(config.application?.category, ""),
|
|
354
|
+
browserRequirements: get(config.application?.browserRequirements, ""),
|
|
355
|
+
featureList: get(config.application?.featureList, []),
|
|
356
|
+
inLanguage: languages,
|
|
357
|
+
name: applicationName,
|
|
358
|
+
operatingSystem: get(config.application?.operatingSystem, ""),
|
|
359
|
+
url: origin
|
|
360
|
+
},
|
|
361
|
+
organization: {
|
|
362
|
+
logo: get(config.organization?.logoUrl, organizationLogo),
|
|
363
|
+
name: get(config.organization?.name, applicationName),
|
|
364
|
+
url: get(config.organization?.url, origin)
|
|
365
|
+
},
|
|
366
|
+
page: {
|
|
367
|
+
description,
|
|
368
|
+
inLanguage: language,
|
|
369
|
+
name: title,
|
|
370
|
+
url: pageUrl
|
|
371
|
+
},
|
|
372
|
+
site: {
|
|
373
|
+
name: applicationName,
|
|
374
|
+
url: origin
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
languageLinks: {
|
|
378
|
+
alternateLanguages: languages,
|
|
379
|
+
canonicalLanguage: config.canonicalLanguage,
|
|
380
|
+
defaultLanguage: config.defaultLanguage,
|
|
381
|
+
host: origin === "" ? "" : new URL(origin).host
|
|
382
|
+
},
|
|
383
|
+
openGraph: {
|
|
384
|
+
description,
|
|
385
|
+
imageAlt: get(config.socialImage.alt, ""),
|
|
386
|
+
imageHeight: get(config.socialImage.height, 630),
|
|
387
|
+
imageUrl: get(config.socialImage.url, ""),
|
|
388
|
+
imageWidth: get(config.socialImage.width, 1200),
|
|
389
|
+
locale: get(config.openGraphLocale, ""),
|
|
390
|
+
siteName: applicationName,
|
|
391
|
+
title,
|
|
392
|
+
url: pageUrl
|
|
393
|
+
},
|
|
394
|
+
twitter: {
|
|
395
|
+
creator: get(config.twitter.creator, ""),
|
|
396
|
+
description,
|
|
397
|
+
imageAlt: get(config.socialImage.alt, ""),
|
|
398
|
+
imageUrl: get(config.socialImage.url, ""),
|
|
399
|
+
site: get(config.twitter.site, ""),
|
|
400
|
+
title,
|
|
401
|
+
url: pageUrl
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
themeColor,
|
|
405
|
+
title
|
|
406
|
+
},
|
|
407
|
+
manifest: {
|
|
408
|
+
backgroundColor: get(config.backgroundColor, themeColor),
|
|
409
|
+
categories: get(config.manifest?.categories, []),
|
|
410
|
+
description,
|
|
411
|
+
display: get(config.manifest?.display, "standalone"),
|
|
412
|
+
icon192,
|
|
413
|
+
icon512,
|
|
414
|
+
id: get(config.manifest?.id, "/"),
|
|
415
|
+
lang: language,
|
|
416
|
+
maskableIcon512: get(config.icons.maskableIcon512, icon512),
|
|
417
|
+
name: applicationName,
|
|
418
|
+
orientation: get(config.manifest?.orientation, "any"),
|
|
419
|
+
scope: get(config.manifest?.scope, "/"),
|
|
420
|
+
screenshots: get(config.manifest?.screenshots, []),
|
|
421
|
+
shortName: get(config.shortName, applicationName),
|
|
422
|
+
shortcuts: get(config.manifest?.shortcuts, []),
|
|
423
|
+
startUrl: `/${language}`,
|
|
424
|
+
themeColor
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
function localizedValue(value, language, defaultLanguage, empty) {
|
|
429
|
+
if (value === void 0) return empty;
|
|
430
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return value;
|
|
431
|
+
const values = value;
|
|
432
|
+
return values[language] ?? values[defaultLanguage] ?? empty;
|
|
433
|
+
}
|
|
255
434
|
//#endregion
|
|
256
435
|
exports.pwaize = pwaize;
|
|
257
436
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["build","transform","minify","build","fileURLToPath","minify","join","mkdir","cp","basename","writeFile","documentMarkup","existsSync","readdir","relative","sep"],"sources":["../src/minifyCss/index.ts","../src/minifyHtml/index.ts","../src/minifyJs/index.ts","../src/webManifest/index.ts","../src/index.ts"],"sourcesContent":["import type { PathLike } from 'node:fs'\nimport { build } from 'esbuild'\nimport { transform } from 'lightningcss'\n\n/** Bundles and minifies a CSS entrypoint into a dense string. */\nexport default async function minifyCss(entrypoint: PathLike): Promise<string> {\n const bundled = await build({\n entryPoints: [entrypoint.toString()],\n bundle: true,\n legalComments: 'none',\n minify: true,\n treeShaking: true,\n write: false,\n })\n const { code } = transform({\n code: bundled.outputFiles[0].contents,\n filename: entrypoint.toString(),\n minify: true,\n })\n\n return new TextDecoder().decode(code).trim()\n}\n","import { minify } from 'html-minifier-terser'\n\n/** Minifies a complete HTML document, including inline CSS and JavaScript. */\nexport default async function minifyHtml(source: string): Promise<string> {\n return minify(source, {\n collapseBooleanAttributes: true,\n collapseInlineTagWhitespace: true,\n collapseWhitespace: true,\n decodeEntities: true,\n html5: true,\n minifyCSS: true,\n minifyJS: {\n compress: {\n dead_code: true,\n passes: 3,\n toplevel: true,\n unused: true,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n },\n removeAttributeQuotes: true,\n removeComments: true,\n removeEmptyAttributes: true,\n removeRedundantAttributes: true,\n sortAttributes: true,\n sortClassName: true,\n useShortDoctype: true,\n })\n}\n","import type { PathLike } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { build } from 'esbuild'\nimport { minify } from 'terser'\n\ntype JavaScriptInput = PathLike | { source: string }\n\ntype MinifyJsOptions = {\n define?: Record<string, string>\n passes?: number\n}\n\n/** Bundles, tree-shakes, mangles, and repeatedly minifies JavaScript. */\nexport default async function minifyJs(\n input: JavaScriptInput,\n { define, passes = 3 }: MinifyJsOptions = {}\n): Promise<string> {\n const bundled = await build({\n ...(typeof input === 'object' && 'source' in input\n ? { stdin: { contents: input.source, resolveDir: process.cwd() } }\n : {\n entryPoints: [\n input instanceof URL ? fileURLToPath(input) : input.toString(),\n ],\n }),\n bundle: true,\n define,\n format: 'esm',\n legalComments: 'none',\n minify: true,\n platform: 'browser',\n treeShaking: true,\n write: false,\n })\n\n let output = bundled.outputFiles[0].text\n\n for (let round = 0; round < passes; round += 1) {\n const result = await minify(output, {\n compress: {\n dead_code: true,\n passes,\n toplevel: true,\n unused: true,\n },\n ecma: 2024,\n format: {\n beautify: false,\n comments: false,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n })\n\n if (result.code === undefined) {\n throw new Error('Terser did not produce JavaScript output')\n }\n\n output = result.code\n }\n\n return output\n}\n","import type { BCP47LanguageTag } from '@sovereignbase/utils'\n\ntype Path = `/${string}`\ntype ImageURL = Path | `https://${string}`\n\nexport interface WebManifestScreenshot {\n src: ImageURL\n sizes: `${number}x${number}`\n type?: `image/${string}`\n form_factor?: 'narrow' | 'wide'\n label?: string\n}\n\nexport interface WebManifestShortcut {\n name: string\n url: Path\n description?: string\n icons?: {\n src: ImageURL\n sizes: `${number}x${number}` | 'any'\n type?: `image/${string}`\n }[]\n}\n\nexport interface WebManifestOptions {\n name: string\n shortName: string\n description: string\n startUrl: Path\n themeColor: string\n icon192: ImageURL\n icon512: ImageURL\n maskableIcon512: ImageURL\n id?: Path\n scope?: Path\n backgroundColor?: string\n lang?: BCP47LanguageTag\n display?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser'\n orientation?:\n | 'any'\n | 'natural'\n | 'portrait'\n | 'portrait-primary'\n | 'portrait-secondary'\n | 'landscape'\n | 'landscape-primary'\n | 'landscape-secondary'\n categories?: string[]\n screenshots?: WebManifestScreenshot[]\n shortcuts?: WebManifestShortcut[]\n}\n\n/**\n * Generates a standards-based Web App Manifest JSON string.\n */\nexport const webManifest = ({\n name,\n shortName,\n description,\n startUrl,\n themeColor,\n icon192,\n icon512,\n maskableIcon512,\n id = '/',\n scope = '/',\n backgroundColor = themeColor,\n lang,\n display = 'standalone',\n orientation,\n categories,\n screenshots,\n shortcuts,\n}: WebManifestOptions): string =>\n JSON.stringify({\n id,\n name,\n short_name: shortName,\n description,\n start_url: startUrl,\n scope,\n display,\n theme_color: themeColor,\n background_color: backgroundColor,\n ...(lang ? { lang } : {}),\n ...(orientation ? { orientation } : {}),\n ...(categories?.length ? { categories } : {}),\n ...(screenshots?.length ? { screenshots } : {}),\n ...(shortcuts?.length ? { shortcuts } : {}),\n icons: [\n {\n src: icon192,\n sizes: '192x192',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: icon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: maskableIcon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'maskable',\n },\n ],\n })\n","import { existsSync, type PathLike } from 'node:fs'\nimport { cp, mkdir, readdir, writeFile } from 'node:fs/promises'\nimport { basename, join, relative, sep } from 'node:path'\nimport type { BCP47LanguageTag } from '@sovereignbase/utils'\nimport type { DocumentMarkupOptions } from './.types/index.js'\nimport { documentMarkup } from './htmlDocument/index.js'\nimport minifyCss from './minifyCss/index.js'\nimport minifyHtml from './minifyHtml/index.js'\nimport minifyJs from './minifyJs/index.js'\nimport { webManifest, type WebManifestOptions } from './webManifest/index.js'\n\nexport async function pwaize(config: PWAizeConfig): Promise<void> {\n const outputDirectory = join(config.outDir.toString(), 'web')\n const buildId = crypto.randomUUID()\n const minifyPasses = config.minifyPasses ?? 3\n const serviceWorkerPath = '/ServiceWorker'\n\n await mkdir(outputDirectory, { recursive: true })\n\n for (const directory of [config.assetsDir, config.i18nDir]) {\n if (directory === undefined) continue\n\n const sourceDirectory = directory.toString()\n await cp(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n {\n recursive: true,\n }\n )\n }\n\n const stylesheet = await minifyCss(config.stylesheet)\n const entrypoint = await minifyJs(config.entrypoint, {\n passes: minifyPasses,\n })\n const installer = await minifyJs(\n {\n source: `const registration=await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:\"/\",type:\"module\"});await navigator.serviceWorker.ready;if(!navigator.serviceWorker.controller)location.reload();`,\n },\n { passes: minifyPasses }\n )\n const languages = [config.defaultLanguage, ...config.alternateLanguages]\n\n for (const language of languages) {\n const localized = config.languages[language]\n if (localized === undefined) {\n throw new Error(`Missing PWA configuration for language \"${language}\"`)\n }\n\n const languageDirectory = join(outputDirectory, language)\n const manifestPath = `/${language}/manifest.webmanifest` as const\n const manifest = webManifest({\n ...localized.manifest,\n lang: language,\n })\n\n await mkdir(languageDirectory, { recursive: true })\n await writeFile(join(languageDirectory, 'manifest.webmanifest'), manifest)\n\n const installerDocument = await minifyHtml(\n await documentMarkup({\n ...localized.document,\n language,\n stylesheet: '',\n entrypoint: installer,\n manifestUrl: manifestPath,\n })\n )\n\n await writeFile(join(languageDirectory, 'index.html'), installerDocument)\n\n if (language === config.defaultLanguage) {\n await writeFile(join(outputDirectory, 'index.html'), installerDocument)\n await writeFile(join(outputDirectory, 'manifest.webmanifest'), manifest)\n }\n }\n\n const buildIdPath = join(\n outputDirectory,\n '@sovereignbase',\n 'pwa',\n 'pwaize-build-id.txt'\n )\n await mkdir(join(outputDirectory, '@sovereignbase', 'pwa'), {\n recursive: true,\n })\n await writeFile(buildIdPath, buildId)\n\n if (config._headersFile === true) {\n await writeFile(\n join(outputDirectory, '_headers'),\n `/${serviceWorkerPath.slice(1)}\\n Cache-Control: no-cache\\n Content-Type: text/javascript;charset=UTF-8\\n\\n/*\\n X-Content-Type-Options: nosniff\\n`\n )\n }\n\n const precache = [\n ...(await publicFiles(outputDirectory)),\n ...(config.serviceWorker?.precache ?? []),\n ]\n const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule)\n const compiledServiceWorker = new URL(\n './serviceWorker/entrypoint.js',\n import.meta.url\n )\n const serviceWorker = await minifyJs(\n existsSync(compiledServiceWorker)\n ? compiledServiceWorker\n : new URL('./serviceWorker/entrypoint.ts', import.meta.url),\n {\n define: {\n buildId: JSON.stringify(buildId),\n buildIdUrl: JSON.stringify('/@sovereignbase/pwa/pwaize-build-id.txt'),\n bypassRules: JSON.stringify(bypassRules),\n customInitialize:\n config.serviceWorker?.initialize === undefined\n ? 'undefined'\n : `(${config.serviceWorker.initialize.toString()})`,\n customWaitUntil:\n config.serviceWorker?.waitUntil === undefined\n ? 'undefined'\n : `(${config.serviceWorker.waitUntil.toString()})`,\n defaultLanguage: JSON.stringify(config.defaultLanguage),\n documentOptions: JSON.stringify(\n Object.fromEntries(\n languages.map((language) => [\n language,\n config.languages[language].document,\n ])\n )\n ),\n entrypoint: JSON.stringify(entrypoint),\n precache: JSON.stringify(precache),\n stylesheet: JSON.stringify(stylesheet),\n },\n passes: minifyPasses,\n }\n )\n\n await writeFile(\n join(outputDirectory, serviceWorkerPath.slice(1)),\n serviceWorker\n )\n}\n\nasync function publicFiles(\n directory: string,\n root = directory\n): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true })\n const files: string[] = []\n\n for (const entry of entries) {\n const path = join(directory, entry.name)\n if (entry.isDirectory()) {\n files.push(...(await publicFiles(path, root)))\n } else if (entry.isFile() && entry.name !== '_headers') {\n files.push(`/${relative(root, path).split(sep).join('/')}`)\n }\n }\n\n return files.sort()\n}\n\nfunction globRule(pattern: string | RegExp): {\n absolute: boolean\n flags: string\n source: string\n} {\n if (pattern instanceof RegExp) {\n return {\n absolute: true,\n flags: pattern.flags,\n source: pattern.source,\n }\n }\n\n let source = '^'\n for (let index = 0; index < pattern.length; index += 1) {\n const character = pattern[index]\n\n if (character === '*') {\n if (pattern[index + 1] === '*') {\n source += '.*'\n index += 1\n } else {\n source += '[^/]*'\n }\n } else if (character === '?') {\n source += '.'\n } else {\n source += character.replace(/[|\\\\{}()[\\]^$+?.]/g, '\\\\$&')\n }\n }\n\n return {\n absolute: pattern.includes('://'),\n flags: '',\n source: `${source}$`,\n }\n}\n\nexport type PWAizeConfig = {\n defaultLanguage: BCP47LanguageTag\n canonicalLanguage: BCP47LanguageTag\n alternateLanguages: BCP47LanguageTag[]\n\n languages: Record<\n string,\n {\n document: Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n manifest: Omit<WebManifestOptions, 'lang'>\n }\n >\n\n stylesheet: PathLike\n entrypoint: PathLike\n outDir: PathLike\n\n assetsDir?: PathLike\n i18nDir?: PathLike\n minifyPasses?: number\n\n serviceWorker?: {\n bypass?: Array<string | RegExp>\n precache?: `/${string}`[]\n initialize?: () => void\n waitUntil?: () => Promise<void>\n }\n\n _headersFile?: boolean\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["minifiedOutputs","build","transform","minifiedOutputs","minify","build","fileURLToPath","minify","join","mkdir","cp","basename","writeFile","documentMarkup","existsSync","readdir","relative","extname","dirname","createHash","readFile","sep"],"sources":["../src/minifyCss/index.ts","../src/minifyHtml/index.ts","../src/minifyJs/index.ts","../src/webManifest/index.ts","../src/index.ts"],"sourcesContent":["import type { PathLike } from 'node:fs'\nimport { build } from 'esbuild'\nimport { transform } from 'lightningcss'\n\nconst minifiedOutputs = new Map<string, string>()\n\n/** Bundles and minifies a CSS entrypoint into a dense string. */\nexport default async function minifyCss(entrypoint: PathLike): Promise<string> {\n const bundled = await build({\n entryPoints: [entrypoint.toString()],\n bundle: true,\n legalComments: 'none',\n minify: true,\n treeShaking: true,\n write: false,\n external: ['/assets/*'],\n })\n const source = bundled.outputFiles[0].text\n const cached = minifiedOutputs.get(source)\n if (cached !== undefined) return cached\n\n const { code } = transform({\n code: bundled.outputFiles[0].contents,\n filename: entrypoint.toString(),\n minify: true,\n })\n\n const output = new TextDecoder().decode(code).trim()\n minifiedOutputs.set(source, output)\n return output\n}\n","import { minify } from 'html-minifier-terser'\n\nconst minifiedOutputs = new Map<string, string>()\n\n/** Minifies a complete HTML document, including inline CSS and JavaScript. */\nexport default async function minifyHtml(source: string): Promise<string> {\n const cached = minifiedOutputs.get(source)\n if (cached !== undefined) return cached\n\n const output = await minify(source, {\n collapseBooleanAttributes: true,\n collapseInlineTagWhitespace: true,\n collapseWhitespace: true,\n decodeEntities: true,\n html5: true,\n minifyCSS: true,\n minifyJS: {\n compress: {\n dead_code: true,\n passes: 3,\n toplevel: true,\n unused: true,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n },\n removeAttributeQuotes: true,\n removeComments: true,\n removeEmptyAttributes: true,\n removeRedundantAttributes: true,\n sortAttributes: true,\n sortClassName: true,\n useShortDoctype: true,\n })\n minifiedOutputs.set(source, output)\n return output\n}\n","import type { PathLike } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { build } from 'esbuild'\nimport { minify } from 'terser'\n\nconst minifiedOutputs = new Map<string, string>()\n\ntype JavaScriptInput = PathLike | { source: string }\n\ntype MinifyJsOptions = {\n banner?: string\n define?: Record<string, string>\n passes?: number\n}\n\n/** Bundles, tree-shakes, mangles, and repeatedly minifies JavaScript. */\nexport default async function minifyJs(\n input: JavaScriptInput,\n { banner, define, passes = 3 }: MinifyJsOptions = {}\n): Promise<string> {\n const bundled = await build({\n ...(typeof input === 'object' && 'source' in input\n ? { stdin: { contents: input.source, resolveDir: process.cwd() } }\n : {\n entryPoints: [\n input instanceof URL ? fileURLToPath(input) : input.toString(),\n ],\n }),\n bundle: true,\n banner: banner === undefined ? undefined : { js: banner },\n define,\n format: 'esm',\n legalComments: 'none',\n minify: true,\n platform: 'browser',\n treeShaking: true,\n write: false,\n })\n\n const output = bundled.outputFiles[0].text\n const cacheKey = `${passes}\\0${output}`\n const cached = minifiedOutputs.get(cacheKey)\n if (cached !== undefined) return cached\n\n const result = await repeatedlyMinify(output, passes)\n minifiedOutputs.set(cacheKey, result)\n return result\n}\n\nasync function repeatedlyMinify(\n source: string,\n passes: number\n): Promise<string> {\n let output = source\n\n for (let round = 0; round < passes; round += 1) {\n const result = await minify(output, {\n compress: {\n dead_code: true,\n passes,\n toplevel: true,\n unused: true,\n },\n ecma: 2024,\n format: {\n beautify: false,\n comments: false,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n })\n\n /* v8 ignore next 3 -- Terser returns code or rejects for this input form. */\n if (result.code === undefined) {\n throw new Error('Terser did not produce JavaScript output')\n }\n\n output = result.code\n }\n\n return output\n}\n","import type { BCP47LanguageTag } from '@sovereignbase/utils'\n\ntype Path = `/${string}`\ntype ImageURL = Path | `https://${string}`\n\nexport interface WebManifestScreenshot {\n src: ImageURL\n sizes: `${number}x${number}`\n type?: `image/${string}`\n form_factor?: 'narrow' | 'wide'\n label?: string\n}\n\nexport interface WebManifestShortcut {\n name: string\n url: Path\n description?: string\n icons?: {\n src: ImageURL\n sizes: `${number}x${number}` | 'any'\n type?: `image/${string}`\n }[]\n}\n\nexport interface WebManifestOptions {\n name: string\n shortName: string\n description: string\n startUrl: Path\n themeColor: string\n icon192: ImageURL\n icon512: ImageURL\n maskableIcon512: ImageURL\n id?: Path\n scope?: Path\n backgroundColor?: string\n lang?: BCP47LanguageTag\n display?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser'\n orientation?:\n | 'any'\n | 'natural'\n | 'portrait'\n | 'portrait-primary'\n | 'portrait-secondary'\n | 'landscape'\n | 'landscape-primary'\n | 'landscape-secondary'\n categories?: string[]\n screenshots?: WebManifestScreenshot[]\n shortcuts?: WebManifestShortcut[]\n}\n\n/**\n * Generates a standards-based Web App Manifest JSON string.\n */\nexport const webManifest = ({\n name,\n shortName,\n description,\n startUrl,\n themeColor,\n icon192,\n icon512,\n maskableIcon512,\n id = '/',\n scope = '/',\n backgroundColor = themeColor,\n lang,\n display = 'standalone',\n orientation,\n categories,\n screenshots,\n shortcuts,\n}: WebManifestOptions): string =>\n JSON.stringify({\n id,\n name,\n short_name: shortName,\n description,\n start_url: startUrl,\n scope,\n display,\n theme_color: themeColor,\n background_color: backgroundColor,\n ...(lang ? { lang } : {}),\n ...(orientation ? { orientation } : {}),\n ...(categories?.length ? { categories } : {}),\n ...(screenshots?.length ? { screenshots } : {}),\n ...(shortcuts?.length ? { shortcuts } : {}),\n icons: [\n {\n src: icon192,\n sizes: '192x192',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: icon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: maskableIcon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'maskable',\n },\n ],\n })\n","import { createHash } from 'node:crypto'\nimport { existsSync, type PathLike } from 'node:fs'\nimport { cp, mkdir, readFile, readdir, writeFile } from 'node:fs/promises'\nimport { basename, dirname, extname, join, relative, sep } from 'node:path'\nimport type { BCP47LanguageTag, OpenGraphLocale } from '@sovereignbase/utils'\nimport type {\n DocumentMarkupOptions,\n HTTPSUrl,\n URLPath,\n} from './.types/index.js'\nimport { documentMarkup } from './htmlDocument/index.js'\nimport minifyCss from './minifyCss/index.js'\nimport minifyHtml from './minifyHtml/index.js'\nimport minifyJs from './minifyJs/index.js'\nimport {\n webManifest,\n type WebManifestOptions,\n type WebManifestScreenshot,\n type WebManifestShortcut,\n} from './webManifest/index.js'\n\nexport async function pwaize(config: PWAizeConfig): Promise<void> {\n const outputDirectory = join(config.outDir.toString(), 'web')\n const languages = [\n ...new Set([config.defaultLanguage, ...config.alternateLanguages]),\n ]\n const minifyPasses = config.minifyPasses ?? 3\n const serviceWorkerPath = '/ServiceWorker'\n\n await mkdir(outputDirectory, { recursive: true })\n\n if (config.assetsDir !== undefined) {\n const sourceDirectory = config.assetsDir.toString()\n await cp(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n { recursive: true }\n )\n }\n\n if (config.i18nDir !== undefined) {\n const sourceDirectory = config.i18nDir.toString()\n await buildScriptDirectory(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n minifyPasses\n )\n }\n\n const stylesheet = await minifyCss(config.stylesheet)\n const entrypoint = await minifyJs(config.entrypoint, {\n passes: minifyPasses,\n })\n const installer = await minifyJs(\n {\n source: `await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:\"/\",type:\"module\"});await navigator.serviceWorker.ready;location.reload();`,\n },\n { passes: minifyPasses }\n )\n const documentOptions: Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n > = {}\n\n for (const language of languages) {\n const localized = localizeConfig(config, language, languages)\n const languageDirectory = join(outputDirectory, language)\n const manifestPath = `/${language}/manifest.webmanifest` as const\n const manifest = webManifest(localized.manifest)\n documentOptions[language] = localized.document\n\n await mkdir(languageDirectory, { recursive: true })\n await writeFile(join(languageDirectory, 'manifest.webmanifest'), manifest)\n\n const installerDocument = await minifyHtml(\n await documentMarkup({\n ...localized.document,\n entrypoint: installer,\n language,\n manifestUrl: manifestPath,\n })\n )\n await writeFile(join(languageDirectory, 'index.html'), installerDocument)\n\n if (language === config.defaultLanguage) {\n await writeFile(join(outputDirectory, 'index.html'), installerDocument)\n await writeFile(join(outputDirectory, 'manifest.webmanifest'), manifest)\n }\n }\n\n if (config._headersFile === true) {\n await writeFile(\n join(outputDirectory, '_headers'),\n `/${serviceWorkerPath.slice(1)}\\n Cache-Control: no-cache\\n Content-Type: text/javascript;charset=UTF-8\\n\\n/*\\n X-Content-Type-Options: nosniff\\n`\n )\n }\n\n const buildIdUrl = '/@sovereignbase/pwa/pwaize-build-id.txt'\n const generatedFiles = (await publicFiles(outputDirectory)).filter(\n (url) => url !== serviceWorkerPath && url !== buildIdUrl\n )\n const precache = [\n ...new Set([...generatedFiles, ...(config.serviceWorker?.precache ?? [])]),\n ].sort()\n const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule)\n const initialize =\n config.serviceWorker?.initialize === undefined\n ? 'undefined'\n : functionExpression(config.serviceWorker.initialize)\n const waitUntil =\n config.serviceWorker?.waitUntil === undefined\n ? 'undefined'\n : functionExpression(config.serviceWorker.waitUntil)\n const buildId = await contentBuildId(outputDirectory, generatedFiles, {\n bypassRules,\n documentOptions,\n entrypoint,\n initialize,\n precache,\n stylesheet,\n waitUntil,\n })\n const buildIdDirectory = join(outputDirectory, '@sovereignbase', 'pwa')\n await mkdir(buildIdDirectory, { recursive: true })\n await writeFile(join(buildIdDirectory, 'pwaize-build-id.txt'), buildId)\n const compiledServiceWorker = new URL(\n './serviceWorker/entrypoint.js',\n import.meta.url\n )\n const serviceWorker = await minifyJs(\n /* v8 ignore next -- the packaged .js path is exercised by runtime tests */\n existsSync(compiledServiceWorker)\n ? compiledServiceWorker\n : new URL('./serviceWorker/entrypoint.ts', import.meta.url),\n {\n banner: `const __pwaInitialize=${initialize},__pwaWaitUntil=${waitUntil};`,\n define: {\n buildId: JSON.stringify(buildId),\n buildIdUrl: JSON.stringify(buildIdUrl),\n bypassRules: JSON.stringify(bypassRules),\n customInitialize: '__pwaInitialize',\n customWaitUntil: '__pwaWaitUntil',\n defaultLanguage: JSON.stringify(config.defaultLanguage),\n documentOptions: JSON.stringify(documentOptions),\n entrypoint: JSON.stringify(entrypoint),\n precache: JSON.stringify(precache),\n stylesheet: JSON.stringify(stylesheet),\n },\n passes: minifyPasses,\n }\n )\n\n await writeFile(\n join(outputDirectory, serviceWorkerPath.slice(1)),\n serviceWorker\n )\n}\n\nasync function buildScriptDirectory(\n sourceDirectory: string,\n outputDirectory: string,\n passes: number,\n root = sourceDirectory\n): Promise<void> {\n for (const entry of await readdir(sourceDirectory, { withFileTypes: true })) {\n const source = join(sourceDirectory, entry.name)\n if (entry.isDirectory()) {\n await buildScriptDirectory(source, outputDirectory, passes, root)\n continue\n }\n if (!entry.isFile() || entry.name.endsWith('.d.ts')) continue\n\n const relativePath = relative(root, source)\n const extension = extname(relativePath)\n const output = join(\n outputDirectory,\n /\\.[cm]?[jt]sx?$/.test(extension)\n ? `${relativePath.slice(0, -extension.length)}.js`\n : relativePath\n )\n await mkdir(dirname(output), { recursive: true })\n if (/\\.[cm]?[jt]sx?$/.test(extension)) {\n await writeFile(output, await minifyJs(source, { passes }))\n } else {\n await cp(source, output)\n }\n }\n}\n\nasync function contentBuildId(\n outputDirectory: string,\n files: string[],\n configuration: unknown\n): Promise<string> {\n const hash = createHash('sha256')\n hash.update(JSON.stringify(configuration))\n for (const file of files) {\n hash.update(file)\n hash.update(\n await readFile(join(outputDirectory, ...file.slice(1).split('/')))\n )\n }\n return hash.digest('hex')\n}\n\nasync function publicFiles(\n directory: string,\n root = directory\n): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true })\n const files: string[] = []\n\n for (const entry of entries) {\n const path = join(directory, entry.name)\n if (entry.isDirectory()) {\n files.push(...(await publicFiles(path, root)))\n } else if (entry.isFile() && entry.name !== '_headers') {\n files.push(`/${relative(root, path).split(sep).join('/')}`)\n }\n }\n\n return files.sort()\n}\n\nfunction globRule(pattern: string | RegExp): {\n absolute: boolean\n flags: string\n source: string\n} {\n if (pattern instanceof RegExp) {\n return { absolute: true, flags: pattern.flags, source: pattern.source }\n }\n\n let source = '^'\n for (let index = 0; index < pattern.length; index += 1) {\n const character = pattern[index]\n if (character === '*') {\n if (pattern[index + 1] === '*') {\n source += '.*'\n index += 1\n } else {\n source += '[^/]*'\n }\n } else if (character === '?') {\n source += '.'\n } else {\n source += character.replace(/[|\\\\{}()[\\]^$+?.]/g, '\\\\$&')\n }\n }\n\n return {\n absolute: pattern.includes('://'),\n flags: '',\n source: `${source}$`,\n }\n}\n\nfunction functionExpression(\n callback: (...arguments_: never[]) => unknown\n): string {\n const source = callback.toString()\n if (/^(?:async\\s+)?function\\b|^(?:async\\s+)?\\(/.test(source)) {\n return `(${source})`\n }\n if (source.startsWith('async ')) {\n return `(async function ${source.slice('async '.length)})`\n }\n return `(function ${source})`\n}\n\nfunction localizeConfig(\n config: PWAizeConfig,\n language: BCP47LanguageTag,\n languages: BCP47LanguageTag[]\n): {\n document: Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n manifest: WebManifestOptions\n} {\n const get = <T>(value: Localized<T> | undefined, empty: T): T =>\n localizedValue(value, language, config.defaultLanguage, empty)\n const applicationName = get(config.applicationName, '')\n const description = get(config.description, '')\n const icon192 = get<string>(config.icons.icon192, '')\n const icon512 = get<string>(config.icons.icon512, '')\n const origin = get<string>(config.origin, '')\n const pageUrl = (\n origin === '' ? '' : new URL(`/${language}`, origin).href\n ) as HTTPSUrl\n const organizationLogo = (\n origin === '' || icon512 === '' ? '' : new URL(icon512, origin).href\n ) as HTTPSUrl\n const themeColor = get(config.themeColor, '')\n const title = get(config.title, '')\n\n return {\n document: {\n applicationName,\n appleStatusBarStyle: get(config.appleStatusBarStyle, 'black-translucent'),\n appleTouchIconUrl: get(\n config.icons.appleTouchIconUrl,\n icon192 as URLPath\n ),\n bodyMarkup: get(config.bodyMarkup, ''),\n colorScheme: get(config.colorScheme, 'light dark'),\n headMarkup: get(config.headMarkup, ''),\n iconUrl: get(config.icons.iconUrl, icon512 as URLPath),\n maskIconColor: themeColor,\n maskIconUrl: get(config.icons.maskIconUrl, '' as URLPath),\n seo: {\n jsonLD: {\n application: {\n applicationCategory: get(config.application?.category, ''),\n browserRequirements: get(\n config.application?.browserRequirements,\n ''\n ),\n featureList: get(config.application?.featureList, []),\n inLanguage: languages,\n name: applicationName,\n operatingSystem: get(config.application?.operatingSystem, ''),\n url: origin as HTTPSUrl,\n },\n organization: {\n logo: get(config.organization?.logoUrl, organizationLogo),\n name: get(config.organization?.name, applicationName),\n url: get<string>(config.organization?.url, origin) as HTTPSUrl,\n },\n page: {\n description,\n inLanguage: language,\n name: title,\n url: pageUrl,\n },\n site: { name: applicationName, url: origin as HTTPSUrl },\n },\n languageLinks: {\n alternateLanguages: languages,\n canonicalLanguage: config.canonicalLanguage,\n defaultLanguage: config.defaultLanguage,\n host: (origin === ''\n ? ''\n : new URL(origin).host) as `${string}.${string}`,\n },\n openGraph: {\n description,\n imageAlt: get(config.socialImage.alt, ''),\n imageHeight: get(config.socialImage.height, 630),\n imageUrl: get(config.socialImage.url, '' as HTTPSUrl),\n imageWidth: get(config.socialImage.width, 1200),\n locale: get(config.openGraphLocale, '' as OpenGraphLocale),\n siteName: applicationName,\n title,\n url: pageUrl,\n },\n twitter: {\n creator: get(config.twitter.creator, '' as `@${string}`),\n description,\n imageAlt: get(config.socialImage.alt, ''),\n imageUrl: get(config.socialImage.url, '' as HTTPSUrl),\n site: get(config.twitter.site, '' as `@${string}`),\n title,\n url: pageUrl,\n },\n },\n themeColor,\n title,\n },\n manifest: {\n backgroundColor: get(config.backgroundColor, themeColor),\n categories: get(config.manifest?.categories, []),\n description,\n display: get(config.manifest?.display, 'standalone'),\n icon192: icon192 as URLPath,\n icon512: icon512 as URLPath,\n id: get(config.manifest?.id, '/' as URLPath),\n lang: language,\n maskableIcon512: get(config.icons.maskableIcon512, icon512 as URLPath),\n name: applicationName,\n orientation: get(config.manifest?.orientation, 'any'),\n scope: get(config.manifest?.scope, '/' as URLPath),\n screenshots: get(config.manifest?.screenshots, []),\n shortName: get(config.shortName, applicationName),\n shortcuts: get(config.manifest?.shortcuts, []),\n startUrl: `/${language}`,\n themeColor,\n },\n }\n}\n\nfunction localizedValue<T>(\n value: Localized<T> | undefined,\n language: BCP47LanguageTag,\n defaultLanguage: BCP47LanguageTag,\n empty: T\n): T {\n if (value === undefined) return empty\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return value as T\n }\n\n const values = value as Partial<Record<BCP47LanguageTag, T>>\n return values[language] ?? values[defaultLanguage] ?? empty\n}\n\nexport type Localized<T> = T | Partial<Record<BCP47LanguageTag, T>>\n\nexport type PWAizeConfig = {\n _headersFile?: boolean\n alternateLanguages: BCP47LanguageTag[]\n application?: {\n browserRequirements?: Localized<string>\n category?: Localized<string>\n featureList?: Localized<string[]>\n operatingSystem?: Localized<string>\n }\n applicationName: Localized<string>\n appleStatusBarStyle?: Localized<'black' | 'black-translucent' | 'default'>\n assetsDir?: PathLike\n backgroundColor?: Localized<string>\n bodyMarkup?: Localized<string>\n canonicalLanguage: BCP47LanguageTag\n colorScheme?: Localized<'dark' | 'dark light' | 'light' | 'light dark'>\n defaultLanguage: BCP47LanguageTag\n description: Localized<string>\n entrypoint: PathLike\n headMarkup?: Localized<string>\n i18nDir?: PathLike\n icons: {\n appleTouchIconUrl?: Localized<URLPath>\n icon192: Localized<URLPath>\n icon512: Localized<URLPath>\n iconUrl?: Localized<URLPath>\n maskableIcon512: Localized<URLPath>\n maskIconUrl?: Localized<URLPath>\n }\n manifest?: {\n categories?: Localized<string[]>\n display?: Localized<'browser' | 'fullscreen' | 'minimal-ui' | 'standalone'>\n id?: Localized<URLPath>\n orientation?: Localized<WebManifestOptions['orientation']>\n scope?: Localized<URLPath>\n screenshots?: Localized<WebManifestScreenshot[]>\n shortcuts?: Localized<WebManifestShortcut[]>\n }\n minifyPasses?: number\n openGraphLocale: Localized<OpenGraphLocale>\n organization?: {\n logoUrl?: Localized<HTTPSUrl>\n name?: Localized<string>\n url?: Localized<HTTPSUrl>\n }\n origin: Localized<HTTPSUrl>\n outDir: PathLike\n serviceWorker?: {\n bypass?: Array<string | RegExp>\n initialize?: () => void\n precache?: URLPath[]\n waitUntil?: () => Promise<void>\n }\n shortName?: Localized<string>\n socialImage: {\n alt: Localized<string>\n height?: Localized<number>\n url: Localized<HTTPSUrl>\n width?: Localized<number>\n }\n stylesheet: PathLike\n themeColor: Localized<string>\n title: Localized<string>\n twitter: {\n creator: Localized<`@${string}`>\n site: Localized<`@${string}`>\n }\n}\n"],"mappings":"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"}
|