@michijs/dev-server 0.7.7 → 0.7.9
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/bin/actions/generateAssets.js +50 -20
- package/bin/config/userConfig.js +2 -2
- package/bin/constants.js +24 -0
- package/bin/types.d.ts +12 -1
- package/package.json +8 -7
|
@@ -6,7 +6,25 @@ import { fileURLToPath } from "url";
|
|
|
6
6
|
import { basename, dirname, resolve } from "path";
|
|
7
7
|
import { getLocalURL } from "../utils/getLocalURL.js";
|
|
8
8
|
import { assetsSizes } from "../constants.js";
|
|
9
|
-
import
|
|
9
|
+
import { chromium } from "playwright-core";
|
|
10
|
+
import { exec } from "child_process";
|
|
11
|
+
import { getColor } from "colorthief";
|
|
12
|
+
async function installPlaywright() {
|
|
13
|
+
console.log("Installing Playwright...");
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
const runners = ["bunx", "npx"];
|
|
16
|
+
exec(runners
|
|
17
|
+
.map((x) => `${x} playwright install chromium --with-deps`)
|
|
18
|
+
.join(" || "), (error, stdout, stderr) => {
|
|
19
|
+
if (error) {
|
|
20
|
+
console.error(`Error during Playwright installation: ${error.message}`);
|
|
21
|
+
return reject(error);
|
|
22
|
+
}
|
|
23
|
+
console.log(stdout);
|
|
24
|
+
resolve();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
10
28
|
const generatedPath = getPath(`${config.public.path}/${config.public.assets.path}/generated`);
|
|
11
29
|
const screenshotsPath = getPath(`${generatedPath}/screenshots`);
|
|
12
30
|
const svgPath = resolve(getPath(dirname(fileURLToPath(import.meta.url))), "../..");
|
|
@@ -21,10 +39,8 @@ const generateFavicon = async (src, dest) => {
|
|
|
21
39
|
};
|
|
22
40
|
config.watch = false;
|
|
23
41
|
config.openBrowser = false;
|
|
24
|
-
const browser = await
|
|
25
|
-
dumpio: true,
|
|
42
|
+
const browser = await chromium.launch({
|
|
26
43
|
headless: true,
|
|
27
|
-
product: "chrome",
|
|
28
44
|
});
|
|
29
45
|
const port = await new Promise(async (resolve) => {
|
|
30
46
|
const { start } = await import("./start.js");
|
|
@@ -33,13 +49,20 @@ const port = await new Promise(async (resolve) => {
|
|
|
33
49
|
async function takeScreenshots({ viewports, options, pageCallback, path, }) {
|
|
34
50
|
return await Promise.all(viewports.map(async (viewport) => {
|
|
35
51
|
// Create a new page
|
|
36
|
-
const page = await browser.newPage(
|
|
37
|
-
|
|
38
|
-
|
|
52
|
+
const page = await browser.newPage({
|
|
53
|
+
reducedMotion: "reduce",
|
|
54
|
+
colorScheme: "dark",
|
|
55
|
+
viewport,
|
|
56
|
+
});
|
|
39
57
|
const suffix = await pageCallback?.(page);
|
|
58
|
+
const optionsResult = options?.(viewport, suffix ? `/${suffix}` : suffix) ?? {};
|
|
59
|
+
await page.goto(`${getLocalURL(port)}${path}`, {
|
|
60
|
+
waitUntil: "load",
|
|
61
|
+
});
|
|
62
|
+
await page.waitForTimeout(3000);
|
|
40
63
|
const screenshot = await page.screenshot({
|
|
41
64
|
fullPage: true,
|
|
42
|
-
...
|
|
65
|
+
...optionsResult,
|
|
43
66
|
});
|
|
44
67
|
await page.close();
|
|
45
68
|
return screenshot;
|
|
@@ -97,25 +120,32 @@ export async function generateScreenshots() {
|
|
|
97
120
|
}))));
|
|
98
121
|
}
|
|
99
122
|
export async function generateAssets(callback, src) {
|
|
123
|
+
await installPlaywright();
|
|
100
124
|
const { default: sharp } = await import("sharp");
|
|
101
125
|
rmSync(generatedPath, { recursive: true, force: true });
|
|
102
126
|
if (!existsSync(generatedPath))
|
|
103
127
|
mkdirSync(screenshotsPath, { recursive: true });
|
|
104
128
|
const image = sharp(src);
|
|
105
129
|
const fileNameWithoutExtension = basename(src).split(".")[0];
|
|
130
|
+
const tempFileName = getPath(`${generatedPath}/${fileNameWithoutExtension}-temp.png`);
|
|
131
|
+
await image.png().toFile(tempFileName);
|
|
132
|
+
const dominantColor = await getColor(tempFileName, 1);
|
|
133
|
+
rmSync(tempFileName, { force: true });
|
|
134
|
+
const color = {
|
|
135
|
+
r: dominantColor[0],
|
|
136
|
+
g: dominantColor[1],
|
|
137
|
+
b: dominantColor[2],
|
|
138
|
+
};
|
|
139
|
+
const flattenImage = image.clone().flatten({ background: color });
|
|
106
140
|
await Promise.all([
|
|
107
|
-
...assetsSizes.webp.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
.resize(x, x)
|
|
116
|
-
.png()
|
|
117
|
-
.toFile(getPath(`${generatedPath}/${fileNameWithoutExtension}-${x}.png`));
|
|
118
|
-
}),
|
|
141
|
+
...assetsSizes.webp.flatMap((x) => [image, flattenImage].map((y) => y
|
|
142
|
+
.resize(x, x)
|
|
143
|
+
.webp()
|
|
144
|
+
.toFile(getPath(`${generatedPath}/${fileNameWithoutExtension}-${x}${y === flattenImage ? "-masked" : ""}.webp`)))),
|
|
145
|
+
...assetsSizes.png.flatMap((x) => [image, flattenImage].map((y) => y
|
|
146
|
+
.resize(x, x)
|
|
147
|
+
.png()
|
|
148
|
+
.toFile(getPath(`${generatedPath}/${fileNameWithoutExtension}-${x}${y === flattenImage ? "-masked" : ""}.png`)))),
|
|
119
149
|
generateFavicon(src, getPath(`${config.public.path}/favicon.ico`)),
|
|
120
150
|
generateFeatureImage(src),
|
|
121
151
|
generateScreenshots(),
|
package/bin/config/userConfig.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from "fs";
|
|
|
2
2
|
import { buildSync as esbuild } from "esbuild";
|
|
3
3
|
import { dirname } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
|
-
import {
|
|
5
|
+
import { defaultProductionConfig } from "../constants.js";
|
|
6
6
|
let config = {};
|
|
7
7
|
if (fs.existsSync("michi.config.ts")) {
|
|
8
8
|
esbuild({
|
|
@@ -23,7 +23,7 @@ if (fs.existsSync("michi.config.ts")) {
|
|
|
23
23
|
// @ts-ignore
|
|
24
24
|
const michiConfig = await import("./michi.config.cjs");
|
|
25
25
|
config = michiConfig.default.default({
|
|
26
|
-
|
|
26
|
+
...defaultProductionConfig,
|
|
27
27
|
environment: process.env.NODE_ENV,
|
|
28
28
|
});
|
|
29
29
|
config.public?.manifest?.options?.file_handlers?.forEach((fileHandler) => {
|
package/bin/constants.js
CHANGED
|
@@ -12,5 +12,29 @@ export const assetsSizes = {
|
|
|
12
12
|
};
|
|
13
13
|
export const defaultProductionConfig = {
|
|
14
14
|
assetsSizes,
|
|
15
|
+
icons: [
|
|
16
|
+
...assetsSizes.webp.map((x) => ({
|
|
17
|
+
src: `/assets/generated/icon-${x}.webp`,
|
|
18
|
+
sizes: `${x}x${x}`,
|
|
19
|
+
type: "image/webp",
|
|
20
|
+
})),
|
|
21
|
+
...assetsSizes.png.map((x) => ({
|
|
22
|
+
src: `/assets/generated/icon-${x}.png`,
|
|
23
|
+
sizes: `${x}x${x}`,
|
|
24
|
+
type: "image/png",
|
|
25
|
+
})),
|
|
26
|
+
...assetsSizes.webp.map((x) => ({
|
|
27
|
+
src: `/assets/generated/icon-${x}-maskable.webp`,
|
|
28
|
+
sizes: `${x}x${x}`,
|
|
29
|
+
type: "image/webp",
|
|
30
|
+
purpose: "maskable",
|
|
31
|
+
})),
|
|
32
|
+
...assetsSizes.png.map((x) => ({
|
|
33
|
+
src: `/assets/generated/icon-${x}-maskable.png`,
|
|
34
|
+
sizes: `${x}x${x}`,
|
|
35
|
+
type: "image/png",
|
|
36
|
+
purpose: "maskable",
|
|
37
|
+
})),
|
|
38
|
+
],
|
|
15
39
|
environment: "PRODUCTION",
|
|
16
40
|
};
|
package/bin/types.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { BuildOptions } from "esbuild";
|
|
2
2
|
import type { ImageResource, WebAppManifest } from "web-app-manifest";
|
|
3
3
|
import type { assetsSizes } from "./constants.js";
|
|
4
|
-
import type { Page } from "
|
|
4
|
+
import type { Page } from "playwright-core";
|
|
5
|
+
export interface Viewport {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
5
9
|
export interface AssetDescriptorWeb {
|
|
6
10
|
namespace: "web";
|
|
7
11
|
site: string;
|
|
@@ -129,10 +133,15 @@ export interface PublicOptions {
|
|
|
129
133
|
options?: ServerWebAppManifest;
|
|
130
134
|
};
|
|
131
135
|
}
|
|
136
|
+
interface ProtocolHandler {
|
|
137
|
+
protocol: string;
|
|
138
|
+
url: string;
|
|
139
|
+
}
|
|
132
140
|
export interface ServerWebAppManifest extends WebAppManifest {
|
|
133
141
|
scope_extensions?: {
|
|
134
142
|
origin: string;
|
|
135
143
|
}[];
|
|
144
|
+
protocol_handlers?: ProtocolHandler[];
|
|
136
145
|
file_handlers?: FileHandler[];
|
|
137
146
|
}
|
|
138
147
|
export interface FileHandler {
|
|
@@ -185,7 +194,9 @@ export interface MichiProcessType {
|
|
|
185
194
|
};
|
|
186
195
|
}
|
|
187
196
|
export interface ServerConfigFactoryProps<T extends string> {
|
|
197
|
+
icons: ImageResource[];
|
|
188
198
|
assetsSizes: typeof assetsSizes;
|
|
189
199
|
environment: T;
|
|
190
200
|
}
|
|
191
201
|
export type ServerConfigFactory<T extends string = DefaultEnvironment> = (props: ServerConfigFactoryProps<T>) => ServerConfig;
|
|
202
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@michijs/dev-server",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.9",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/michijs/dev-server.git"
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@michijs/tsconfig": "0.0.4",
|
|
33
|
-
"
|
|
34
|
-
"@types/
|
|
35
|
-
"
|
|
33
|
+
"@types/node": "22.4.1",
|
|
34
|
+
"@types/yargs": "17.0.33",
|
|
35
|
+
"typescript": "5.5.3"
|
|
36
36
|
},
|
|
37
37
|
"keywords": [
|
|
38
38
|
"react",
|
|
@@ -53,12 +53,13 @@
|
|
|
53
53
|
"node": ">=14.16"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
+
"colorthief": "2.4.0",
|
|
56
57
|
"@types/web-app-manifest": "1.0.8",
|
|
57
|
-
"esbuild": "0.23.
|
|
58
|
+
"esbuild": "0.23.1",
|
|
58
59
|
"node-watch": "0.7.4",
|
|
59
60
|
"open": "10.1.0",
|
|
60
|
-
"
|
|
61
|
-
"sharp": "0.33.
|
|
61
|
+
"playwright-core": "1.46.1",
|
|
62
|
+
"sharp": "0.33.5",
|
|
62
63
|
"yargs": "17.7.2"
|
|
63
64
|
}
|
|
64
65
|
}
|