screenshot-beautify 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +25 -72
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/beautify.ts
|
|
7
|
-
import
|
|
7
|
+
import sharp4 from "sharp";
|
|
8
8
|
|
|
9
9
|
// src/background.ts
|
|
10
10
|
import sharp2 from "sharp";
|
|
@@ -164,16 +164,18 @@ async function createFrame(options) {
|
|
|
164
164
|
const {
|
|
165
165
|
width,
|
|
166
166
|
height,
|
|
167
|
-
titleBarHeight =
|
|
168
|
-
cornerRadius =
|
|
169
|
-
buttonSize =
|
|
167
|
+
titleBarHeight = 40,
|
|
168
|
+
cornerRadius = 12,
|
|
169
|
+
buttonSize = 14
|
|
170
170
|
} = options;
|
|
171
171
|
const buttonY = titleBarHeight / 2;
|
|
172
|
-
const buttonSpacing =
|
|
173
|
-
const firstButtonX =
|
|
174
|
-
const closeColor = "#
|
|
175
|
-
const minimizeColor = "#
|
|
176
|
-
const maximizeColor = "#
|
|
172
|
+
const buttonSpacing = 22;
|
|
173
|
+
const firstButtonX = 20;
|
|
174
|
+
const closeColor = "#FF5F57";
|
|
175
|
+
const minimizeColor = "#FEBC2E";
|
|
176
|
+
const maximizeColor = "#28C840";
|
|
177
|
+
const titleBarColor = "#3C3C3C";
|
|
178
|
+
const contentBgColor = "#2D2D2D";
|
|
177
179
|
const svg = `
|
|
178
180
|
<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
|
|
179
181
|
<defs>
|
|
@@ -183,14 +185,14 @@ async function createFrame(options) {
|
|
|
183
185
|
</defs>
|
|
184
186
|
|
|
185
187
|
<!-- Window background with rounded corners -->
|
|
186
|
-
<rect x="0" y="0" width="${width}" height="${height}" rx="${cornerRadius}" ry="${cornerRadius}" fill="
|
|
188
|
+
<rect x="0" y="0" width="${width}" height="${height}" rx="${cornerRadius}" ry="${cornerRadius}" fill="${contentBgColor}" />
|
|
187
189
|
|
|
188
190
|
<!-- Title bar -->
|
|
189
|
-
<rect x="0" y="0" width="${width}" height="${titleBarHeight}" rx="${cornerRadius}" ry="${cornerRadius}" fill="
|
|
191
|
+
<rect x="0" y="0" width="${width}" height="${titleBarHeight}" rx="${cornerRadius}" ry="${cornerRadius}" fill="${titleBarColor}" />
|
|
190
192
|
<!-- Fill bottom corners of title bar -->
|
|
191
|
-
<rect x="0" y="${cornerRadius}" width="${width}" height="${titleBarHeight - cornerRadius}" fill="
|
|
193
|
+
<rect x="0" y="${cornerRadius}" width="${width}" height="${titleBarHeight - cornerRadius}" fill="${titleBarColor}" />
|
|
192
194
|
|
|
193
|
-
<!-- Window buttons -->
|
|
195
|
+
<!-- Window buttons with subtle inner shadows for depth -->
|
|
194
196
|
<circle cx="${firstButtonX}" cy="${buttonY}" r="${buttonSize / 2}" fill="${closeColor}" />
|
|
195
197
|
<circle cx="${firstButtonX + buttonSpacing}" cy="${buttonY}" r="${buttonSize / 2}" fill="${minimizeColor}" />
|
|
196
198
|
<circle cx="${firstButtonX + buttonSpacing * 2}" cy="${buttonY}" r="${buttonSize / 2}" fill="${maximizeColor}" />
|
|
@@ -199,50 +201,18 @@ async function createFrame(options) {
|
|
|
199
201
|
return sharp3(Buffer.from(svg)).png().toBuffer();
|
|
200
202
|
}
|
|
201
203
|
|
|
202
|
-
// src/shadow.ts
|
|
203
|
-
import sharp4 from "sharp";
|
|
204
|
-
async function createShadow(options) {
|
|
205
|
-
const {
|
|
206
|
-
width,
|
|
207
|
-
height,
|
|
208
|
-
blur = 30,
|
|
209
|
-
opacity = 0.5,
|
|
210
|
-
cornerRadius = 10
|
|
211
|
-
} = options;
|
|
212
|
-
const shadowWidth = width + blur;
|
|
213
|
-
const shadowHeight = height + blur;
|
|
214
|
-
const offsetForSize = blur / 2;
|
|
215
|
-
const svg = `
|
|
216
|
-
<svg width="${shadowWidth}" height="${shadowHeight}" xmlns="http://www.w3.org/2000/svg">
|
|
217
|
-
<rect
|
|
218
|
-
x="${offsetForSize}"
|
|
219
|
-
y="${offsetForSize}"
|
|
220
|
-
width="${width}"
|
|
221
|
-
height="${height}"
|
|
222
|
-
rx="${cornerRadius}"
|
|
223
|
-
ry="${cornerRadius}"
|
|
224
|
-
fill="rgba(0, 0, 0, ${opacity})"
|
|
225
|
-
/>
|
|
226
|
-
</svg>
|
|
227
|
-
`;
|
|
228
|
-
return sharp4(Buffer.from(svg)).blur(blur).png().toBuffer();
|
|
229
|
-
}
|
|
230
|
-
|
|
231
204
|
// src/beautify.ts
|
|
232
205
|
async function beautify(inputPath, outputPath, options = {}) {
|
|
233
206
|
const {
|
|
234
207
|
padding = 80,
|
|
235
|
-
cornerRadius =
|
|
236
|
-
titleBarHeight =
|
|
237
|
-
shadowBlur = 30,
|
|
238
|
-
shadowOffsetX = 0,
|
|
239
|
-
shadowOffsetY = 20,
|
|
208
|
+
cornerRadius = 12,
|
|
209
|
+
titleBarHeight = 40,
|
|
240
210
|
backgroundImage,
|
|
241
211
|
backgroundPreset,
|
|
242
212
|
gradientStart = "#2d3436",
|
|
243
213
|
gradientEnd = "#636e72"
|
|
244
214
|
} = options;
|
|
245
|
-
const inputImage =
|
|
215
|
+
const inputImage = sharp4(inputPath);
|
|
246
216
|
const metadata = await inputImage.metadata();
|
|
247
217
|
if (!metadata.width || !metadata.height) {
|
|
248
218
|
throw new Error("Could not determine image dimensions");
|
|
@@ -251,11 +221,8 @@ async function beautify(inputPath, outputPath, options = {}) {
|
|
|
251
221
|
const imgHeight = metadata.height;
|
|
252
222
|
const framedWidth = imgWidth;
|
|
253
223
|
const framedHeight = imgHeight + titleBarHeight;
|
|
254
|
-
const
|
|
255
|
-
const
|
|
256
|
-
const shadowPadding = shadowBlur * 2 + Math.abs(shadowOffsetY);
|
|
257
|
-
const canvasWidth = totalWidth + shadowPadding;
|
|
258
|
-
const canvasHeight = totalHeight + shadowPadding;
|
|
224
|
+
const canvasWidth = framedWidth + padding * 2;
|
|
225
|
+
const canvasHeight = framedHeight + padding * 2;
|
|
259
226
|
const background = await createBackground({
|
|
260
227
|
width: canvasWidth,
|
|
261
228
|
height: canvasHeight,
|
|
@@ -270,16 +237,8 @@ async function beautify(inputPath, outputPath, options = {}) {
|
|
|
270
237
|
titleBarHeight,
|
|
271
238
|
cornerRadius
|
|
272
239
|
});
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
height: framedHeight,
|
|
276
|
-
blur: shadowBlur,
|
|
277
|
-
cornerRadius
|
|
278
|
-
});
|
|
279
|
-
const frameX = padding + shadowPadding / 2;
|
|
280
|
-
const frameY = padding + shadowPadding / 2;
|
|
281
|
-
const shadowX = frameX + shadowOffsetX - shadowBlur / 2;
|
|
282
|
-
const shadowY = frameY + shadowOffsetY - shadowBlur / 2;
|
|
240
|
+
const frameX = padding;
|
|
241
|
+
const frameY = padding;
|
|
283
242
|
const screenshotX = frameX;
|
|
284
243
|
const screenshotY = frameY + titleBarHeight;
|
|
285
244
|
const cornerMask = Buffer.from(`
|
|
@@ -298,19 +257,13 @@ async function beautify(inputPath, outputPath, options = {}) {
|
|
|
298
257
|
<rect x="${imgWidth - cornerRadius}" y="0" width="${cornerRadius}" height="${cornerRadius}" fill="white"/>
|
|
299
258
|
</svg>
|
|
300
259
|
`);
|
|
301
|
-
const roundedScreenshot = await
|
|
260
|
+
const roundedScreenshot = await sharp4(inputPath).ensureAlpha().composite([
|
|
302
261
|
{
|
|
303
|
-
input: await
|
|
262
|
+
input: await sharp4(cornerMask).png().toBuffer(),
|
|
304
263
|
blend: "dest-in"
|
|
305
264
|
}
|
|
306
265
|
]).png().toBuffer();
|
|
307
|
-
await
|
|
308
|
-
// Shadow layer
|
|
309
|
-
{
|
|
310
|
-
input: shadow,
|
|
311
|
-
left: Math.round(shadowX),
|
|
312
|
-
top: Math.round(shadowY)
|
|
313
|
-
},
|
|
266
|
+
await sharp4(background).composite([
|
|
314
267
|
// Window frame
|
|
315
268
|
{
|
|
316
269
|
input: frame,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "screenshot-beautify",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "CLI tool to beautify screenshots with window frames
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "CLI tool to beautify screenshots with macOS-style window frames and gradient backgrounds",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"cli",
|
|
22
22
|
"image",
|
|
23
23
|
"frame",
|
|
24
|
-
"
|
|
24
|
+
"macos",
|
|
25
|
+
"gradient"
|
|
25
26
|
],
|
|
26
27
|
"author": "",
|
|
27
28
|
"license": "MIT",
|